@railgun-community/waku-broadcaster-client-web 7.0.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 (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +63 -0
  3. package/dist/fees/broadcaster-fee-cache.d.ts +24 -0
  4. package/dist/fees/broadcaster-fee-cache.js +81 -0
  5. package/dist/fees/broadcaster-fee-cache.js.map +1 -0
  6. package/dist/fees/handle-fees-message.d.ts +3 -0
  7. package/dist/fees/handle-fees-message.js +90 -0
  8. package/dist/fees/handle-fees-message.js.map +1 -0
  9. package/dist/filters/address-filter.d.ts +7 -0
  10. package/dist/filters/address-filter.js +21 -0
  11. package/dist/filters/address-filter.js.map +1 -0
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.js +4 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/models/broadcaster-config.d.ts +5 -0
  16. package/dist/models/broadcaster-config.js +6 -0
  17. package/dist/models/broadcaster-config.js.map +1 -0
  18. package/dist/models/constants.d.ts +3 -0
  19. package/dist/models/constants.js +10 -0
  20. package/dist/models/constants.js.map +1 -0
  21. package/dist/models/export-models.d.ts +12 -0
  22. package/dist/models/export-models.js +2 -0
  23. package/dist/models/export-models.js.map +1 -0
  24. package/dist/models/index.d.ts +1 -0
  25. package/dist/models/index.js +2 -0
  26. package/dist/models/index.js.map +1 -0
  27. package/dist/search/best-broadcaster.d.ts +7 -0
  28. package/dist/search/best-broadcaster.js +95 -0
  29. package/dist/search/best-broadcaster.js.map +1 -0
  30. package/dist/status/broadcaster-connection-status.d.ts +6 -0
  31. package/dist/status/broadcaster-connection-status.js +72 -0
  32. package/dist/status/broadcaster-connection-status.js.map +1 -0
  33. package/dist/transact/broadcaster-transact-response.d.ts +13 -0
  34. package/dist/transact/broadcaster-transact-response.js +46 -0
  35. package/dist/transact/broadcaster-transact-response.js.map +1 -0
  36. package/dist/transact/broadcaster-transaction.d.ts +16 -0
  37. package/dist/transact/broadcaster-transaction.js +136 -0
  38. package/dist/transact/broadcaster-transaction.js.map +1 -0
  39. package/dist/transact/index.d.ts +1 -0
  40. package/dist/transact/index.js +2 -0
  41. package/dist/transact/index.js.map +1 -0
  42. package/dist/utils/broadcaster-debug.d.ts +7 -0
  43. package/dist/utils/broadcaster-debug.js +20 -0
  44. package/dist/utils/broadcaster-debug.js.map +1 -0
  45. package/dist/utils/broadcaster-util.d.ts +7 -0
  46. package/dist/utils/broadcaster-util.js +49 -0
  47. package/dist/utils/broadcaster-util.js.map +1 -0
  48. package/dist/utils/conversion.d.ts +4 -0
  49. package/dist/utils/conversion.js +14 -0
  50. package/dist/utils/conversion.js.map +1 -0
  51. package/dist/utils/is-defined.d.ts +1 -0
  52. package/dist/utils/is-defined.js +4 -0
  53. package/dist/utils/is-defined.js.map +1 -0
  54. package/dist/waku/waku-broadcaster-waku-core.d.ts +22 -0
  55. package/dist/waku/waku-broadcaster-waku-core.js +164 -0
  56. package/dist/waku/waku-broadcaster-waku-core.js.map +1 -0
  57. package/dist/waku/waku-observers.d.ts +16 -0
  58. package/dist/waku/waku-observers.js +101 -0
  59. package/dist/waku/waku-observers.js.map +1 -0
  60. package/dist/waku/waku-topics.d.ts +7 -0
  61. package/dist/waku/waku-topics.js +7 -0
  62. package/dist/waku/waku-topics.js.map +1 -0
  63. package/dist/waku-broadcaster-client.d.ts +32 -0
  64. package/dist/waku-broadcaster-client.js +147 -0
  65. package/dist/waku-broadcaster-client.js.map +1 -0
  66. package/package.json +65 -0
@@ -0,0 +1,164 @@
1
+ import { delay, promiseTimeout } from '@railgun-community/shared-models';
2
+ import { waitForRemotePeer, createEncoder } from '@waku/core';
3
+ import { Protocols } from '@waku/interfaces';
4
+ import { WakuObservers } from './waku-observers.js';
5
+ import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
6
+ import { BroadcasterFeeCache } from '../fees/broadcaster-fee-cache.js';
7
+ import { utf8ToBytes } from '../utils/conversion.js';
8
+ import { isDefined } from '../utils/is-defined.js';
9
+ import { bootstrap } from '@libp2p/bootstrap';
10
+ import { createRelayNode } from '@waku/sdk/relay';
11
+ import { WAKU_RAILGUN_DEFAULT_PEERS_WEB, WAKU_RAILGUN_PUB_SUB_TOPIC, } from '../models/constants.js';
12
+ export class WakuBroadcasterWakuCore {
13
+ static hasError = false;
14
+ static waku;
15
+ static MAX_RELAY_RETRIES = 3;
16
+ static pubSubTopic = WAKU_RAILGUN_PUB_SUB_TOPIC;
17
+ static additionalDirectPeers = [];
18
+ static peerDiscoveryTimeout = 60000;
19
+ static initWaku = async (chain) => {
20
+ try {
21
+ await WakuBroadcasterWakuCore.connect();
22
+ if (!WakuBroadcasterWakuCore.waku) {
23
+ BroadcasterDebug.log('No waku instance found');
24
+ return;
25
+ }
26
+ WakuObservers.resetCurrentChain();
27
+ await WakuObservers.setObserversForChain(WakuBroadcasterWakuCore.waku, chain);
28
+ }
29
+ catch (err) {
30
+ if (!(err instanceof Error)) {
31
+ throw err;
32
+ }
33
+ BroadcasterDebug.error(err);
34
+ throw err;
35
+ }
36
+ };
37
+ static reinitWaku = async (chain) => {
38
+ if (isDefined(WakuBroadcasterWakuCore.waku) &&
39
+ WakuBroadcasterWakuCore.waku.isStarted()) {
40
+ await WakuBroadcasterWakuCore.disconnect();
41
+ }
42
+ BroadcasterFeeCache.resetCache(chain);
43
+ await WakuBroadcasterWakuCore.initWaku(chain);
44
+ };
45
+ static setBroadcasterOptions(BroadcasterOptions) {
46
+ if (isDefined(BroadcasterOptions.pubSubTopic)) {
47
+ WakuBroadcasterWakuCore.pubSubTopic = BroadcasterOptions.pubSubTopic;
48
+ }
49
+ if (BroadcasterOptions.additionalDirectPeers) {
50
+ WakuBroadcasterWakuCore.additionalDirectPeers =
51
+ BroadcasterOptions.additionalDirectPeers;
52
+ }
53
+ if (isDefined(BroadcasterOptions.peerDiscoveryTimeout)) {
54
+ WakuBroadcasterWakuCore.peerDiscoveryTimeout =
55
+ BroadcasterOptions.peerDiscoveryTimeout;
56
+ }
57
+ }
58
+ static disconnect = async (removeObservers = false) => {
59
+ if (removeObservers) {
60
+ BroadcasterDebug.log('Disconnecting... Removing Observers.');
61
+ WakuObservers.removeAllObservers();
62
+ }
63
+ await WakuBroadcasterWakuCore.waku?.stop();
64
+ WakuBroadcasterWakuCore.waku = undefined;
65
+ };
66
+ static connect = async () => {
67
+ try {
68
+ WakuBroadcasterWakuCore.hasError = false;
69
+ BroadcasterDebug.log(`Creating waku relay client`);
70
+ const peers = [
71
+ ...WAKU_RAILGUN_DEFAULT_PEERS_WEB,
72
+ ...this.additionalDirectPeers,
73
+ ];
74
+ const waitTimeoutBeforeBootstrap = 250;
75
+ const waku = await createRelayNode({
76
+ pubsubTopics: [WakuBroadcasterWakuCore.pubSubTopic],
77
+ pingKeepAlive: 60,
78
+ relayKeepAlive: 60,
79
+ libp2p: {
80
+ peerDiscovery: [
81
+ bootstrap({
82
+ list: peers,
83
+ timeout: waitTimeoutBeforeBootstrap,
84
+ }),
85
+ ],
86
+ },
87
+ });
88
+ BroadcasterDebug.log('Start Waku.');
89
+ await waku.start();
90
+ BroadcasterDebug.log('Waiting for remote peer.');
91
+ await this.waitForRemotePeer(waku);
92
+ if (!isDefined(waku.relay)) {
93
+ throw new Error('No Waku Relay instantiated.');
94
+ }
95
+ BroadcasterDebug.log('Waku peers:');
96
+ for (const peer of waku.libp2p.getPeers()) {
97
+ BroadcasterDebug.log(JSON.stringify(peer));
98
+ }
99
+ BroadcasterDebug.log('Connected to Waku');
100
+ WakuBroadcasterWakuCore.waku = waku;
101
+ WakuBroadcasterWakuCore.hasError = false;
102
+ }
103
+ catch (err) {
104
+ if (!(err instanceof Error)) {
105
+ throw err;
106
+ }
107
+ WakuBroadcasterWakuCore.hasError = true;
108
+ throw err;
109
+ }
110
+ };
111
+ static getMeshPeerCount() {
112
+ return (this.waku?.relay.getMeshPeers(WAKU_RAILGUN_PUB_SUB_TOPIC).length ?? 0);
113
+ }
114
+ static getPubSubPeerCount() {
115
+ const peers = this.waku?.libp2p.getPeers() ?? [];
116
+ return peers.length;
117
+ }
118
+ static async getLightPushPeerCount() {
119
+ return 0;
120
+ }
121
+ static async getFilterPeerCount() {
122
+ return 0;
123
+ }
124
+ static async waitForRemotePeer(waku) {
125
+ try {
126
+ const protocols = [Protocols.Relay];
127
+ await promiseTimeout(waitForRemotePeer(waku, protocols), WakuBroadcasterWakuCore.peerDiscoveryTimeout);
128
+ }
129
+ catch (err) {
130
+ if (!(err instanceof Error)) {
131
+ throw err;
132
+ }
133
+ BroadcasterDebug.error(err);
134
+ throw new Error(err.message);
135
+ }
136
+ }
137
+ static async relayMessage(data, contentTopic, retry = 0) {
138
+ if (!WakuBroadcasterWakuCore.waku?.relay) {
139
+ throw new Error('Relayer did not receive message. Please try again.');
140
+ }
141
+ const dataString = JSON.stringify(data);
142
+ const payload = utf8ToBytes(dataString);
143
+ const message = { payload };
144
+ try {
145
+ await WakuBroadcasterWakuCore.waku.relay.send(createEncoder({
146
+ contentTopic,
147
+ pubsubTopic: WakuBroadcasterWakuCore.pubSubTopic,
148
+ }), message);
149
+ }
150
+ catch (err) {
151
+ if (!(err instanceof Error)) {
152
+ throw err;
153
+ }
154
+ if (retry < WakuBroadcasterWakuCore.MAX_RELAY_RETRIES) {
155
+ await delay(1000);
156
+ return WakuBroadcasterWakuCore.relayMessage(data, contentTopic, retry + 1);
157
+ }
158
+ else {
159
+ BroadcasterDebug.error(err);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ //# sourceMappingURL=waku-broadcaster-waku-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waku-broadcaster-waku-core.js","sourceRoot":"","sources":["../../src/waku/waku-broadcaster-waku-core.ts"],"names":[],"mappings":"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","sourcesContent":["import { Chain, delay, promiseTimeout } from '@railgun-community/shared-models';\nimport { waitForRemotePeer, createEncoder } from '@waku/core';\nimport { Protocols, IMessage, RelayNode } from '@waku/interfaces';\nimport { WakuObservers } from './waku-observers.js';\nimport { BroadcasterDebug } from '../utils/broadcaster-debug.js';\nimport { BroadcasterFeeCache } from '../fees/broadcaster-fee-cache.js';\nimport { utf8ToBytes } from '../utils/conversion.js';\nimport { isDefined } from '../utils/is-defined.js';\nimport { bootstrap } from '@libp2p/bootstrap';\nimport { createRelayNode } from '@waku/sdk/relay';\nimport { BroadcasterOptions } from '../models/index.js';\nimport {\n WAKU_RAILGUN_DEFAULT_PEERS_NODE,\n WAKU_RAILGUN_DEFAULT_PEERS_WEB,\n WAKU_RAILGUN_PUB_SUB_TOPIC,\n} from '../models/constants.js';\n\nexport class WakuBroadcasterWakuCore {\n static hasError = false;\n\n static waku: Optional<RelayNode>;\n private static MAX_RELAY_RETRIES = 3;\n private static pubSubTopic = WAKU_RAILGUN_PUB_SUB_TOPIC;\n private static additionalDirectPeers: string[] = [];\n private static peerDiscoveryTimeout = 60000;\n\n static initWaku = async (chain: Chain): Promise<void> => {\n try {\n await WakuBroadcasterWakuCore.connect();\n if (!WakuBroadcasterWakuCore.waku) {\n BroadcasterDebug.log('No waku instance found');\n return;\n }\n WakuObservers.resetCurrentChain();\n await WakuObservers.setObserversForChain(\n WakuBroadcasterWakuCore.waku,\n chain,\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 reinitWaku = async (chain: Chain) => {\n if (\n isDefined(WakuBroadcasterWakuCore.waku) &&\n WakuBroadcasterWakuCore.waku.isStarted()\n ) {\n await WakuBroadcasterWakuCore.disconnect();\n }\n\n // Resets connection status to \"Connecting\" for this network.\n BroadcasterFeeCache.resetCache(chain);\n\n await WakuBroadcasterWakuCore.initWaku(chain);\n };\n\n static setBroadcasterOptions(BroadcasterOptions: BroadcasterOptions) {\n if (isDefined(BroadcasterOptions.pubSubTopic)) {\n WakuBroadcasterWakuCore.pubSubTopic = BroadcasterOptions.pubSubTopic;\n }\n if (BroadcasterOptions.additionalDirectPeers) {\n WakuBroadcasterWakuCore.additionalDirectPeers =\n BroadcasterOptions.additionalDirectPeers;\n }\n if (isDefined(BroadcasterOptions.peerDiscoveryTimeout)) {\n WakuBroadcasterWakuCore.peerDiscoveryTimeout =\n BroadcasterOptions.peerDiscoveryTimeout;\n }\n }\n\n static disconnect = async (removeObservers: boolean = false) => {\n if (removeObservers) {\n BroadcasterDebug.log('Disconnecting... Removing Observers.');\n WakuObservers.removeAllObservers();\n }\n await WakuBroadcasterWakuCore.waku?.stop();\n WakuBroadcasterWakuCore.waku = undefined;\n };\n\n private static connect = async (): Promise<void> => {\n try {\n WakuBroadcasterWakuCore.hasError = false;\n\n BroadcasterDebug.log(`Creating waku relay client`);\n\n const peers: string[] = [\n ...WAKU_RAILGUN_DEFAULT_PEERS_WEB,\n ...this.additionalDirectPeers,\n ];\n const waitTimeoutBeforeBootstrap = 250; // 250 ms - default is 1000ms\n const waku: RelayNode = await createRelayNode({\n pubsubTopics: [WakuBroadcasterWakuCore.pubSubTopic],\n pingKeepAlive: 60,\n relayKeepAlive: 60,\n libp2p: {\n peerDiscovery: [\n bootstrap({\n list: peers,\n timeout: waitTimeoutBeforeBootstrap,\n }),\n ],\n },\n });\n\n BroadcasterDebug.log('Start Waku.');\n await waku.start();\n\n BroadcasterDebug.log('Waiting for remote peer.');\n await this.waitForRemotePeer(waku);\n\n if (!isDefined(waku.relay)) {\n throw new Error('No Waku Relay instantiated.');\n }\n\n BroadcasterDebug.log('Waku peers:');\n for (const peer of waku.libp2p.getPeers()) {\n BroadcasterDebug.log(JSON.stringify(peer));\n }\n\n BroadcasterDebug.log('Connected to Waku');\n WakuBroadcasterWakuCore.waku = waku;\n WakuBroadcasterWakuCore.hasError = false;\n } catch (err) {\n if (!(err instanceof Error)) {\n throw err;\n }\n WakuBroadcasterWakuCore.hasError = true;\n throw err;\n }\n };\n\n static getMeshPeerCount(): number {\n return (\n this.waku?.relay.getMeshPeers(WAKU_RAILGUN_PUB_SUB_TOPIC).length ?? 0\n );\n }\n\n static getPubSubPeerCount(): number {\n const peers = this.waku?.libp2p.getPeers() ?? [];\n return peers.length;\n }\n\n static async getLightPushPeerCount(): Promise<number> {\n return 0;\n }\n\n static async getFilterPeerCount(): Promise<number> {\n return 0;\n }\n\n private static async waitForRemotePeer(waku: RelayNode) {\n try {\n const protocols = [Protocols.Relay];\n await promiseTimeout(\n waitForRemotePeer(waku, protocols),\n WakuBroadcasterWakuCore.peerDiscoveryTimeout,\n );\n } catch (err) {\n if (!(err instanceof Error)) {\n throw err;\n }\n BroadcasterDebug.error(err);\n throw new Error(err.message);\n }\n }\n\n static async relayMessage(\n data: object,\n contentTopic: string,\n retry: number = 0,\n ): Promise<void> {\n if (!WakuBroadcasterWakuCore.waku?.relay) {\n throw new Error('Relayer did not receive message. Please try again.');\n }\n\n const dataString = JSON.stringify(data);\n const payload = utf8ToBytes(dataString);\n const message: IMessage = { payload };\n\n try {\n await WakuBroadcasterWakuCore.waku.relay.send(\n createEncoder({\n contentTopic,\n pubsubTopic: WakuBroadcasterWakuCore.pubSubTopic,\n }),\n message,\n );\n } catch (err) {\n if (!(err instanceof Error)) {\n throw err;\n }\n if (retry < WakuBroadcasterWakuCore.MAX_RELAY_RETRIES) {\n await delay(1000);\n return WakuBroadcasterWakuCore.relayMessage(\n data,\n contentTopic,\n retry + 1,\n );\n } else {\n BroadcasterDebug.error(err);\n }\n }\n }\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import { Chain } from '@railgun-community/shared-models';
2
+ import { RelayNode } from '@waku/interfaces';
3
+ export declare class WakuObservers {
4
+ private static currentChain;
5
+ private static currentContentTopics;
6
+ private static currentSubscriptions;
7
+ static setObserversForChain: (waku: Optional<RelayNode>, chain: Chain) => Promise<void>;
8
+ static resetCurrentChain: () => void;
9
+ static removeAllObservers: () => void;
10
+ private static getDecodersForChain;
11
+ static subscribedPeers: string[];
12
+ private static addChainObservers;
13
+ static addTransportSubscription(waku: Optional<RelayNode>, topic: string, callback: (message: any) => void): Promise<void>;
14
+ private static addSubscriptions;
15
+ static getCurrentContentTopics(waku?: RelayNode): string[];
16
+ }
@@ -0,0 +1,101 @@
1
+ import { compareChains } from '@railgun-community/shared-models';
2
+ import { createDecoder } from '@waku/core';
3
+ import { contentTopics } from './waku-topics.js';
4
+ import { handleBroadcasterFeesMessage } from '../fees/handle-fees-message.js';
5
+ import { BroadcasterTransactResponse } from '../transact/broadcaster-transact-response.js';
6
+ import { BroadcasterDebug } from '../utils/broadcaster-debug.js';
7
+ import { isDefined } from '../utils/is-defined.js';
8
+ import { WAKU_RAILGUN_PUB_SUB_TOPIC } from '../models/constants.js';
9
+ export class WakuObservers {
10
+ static currentChain;
11
+ static currentContentTopics = [];
12
+ static currentSubscriptions = [];
13
+ static setObserversForChain = async (waku, chain) => {
14
+ if (!waku) {
15
+ return;
16
+ }
17
+ if (WakuObservers.currentChain &&
18
+ compareChains(WakuObservers.currentChain, chain)) {
19
+ return;
20
+ }
21
+ BroadcasterDebug.log(`Add Waku observers for chain: ${chain.type}:${chain.id}`);
22
+ WakuObservers.currentChain = chain;
23
+ WakuObservers.removeAllObservers();
24
+ await WakuObservers.addChainObservers(waku, chain);
25
+ BroadcasterDebug.log(`Waku listening for events on chain: ${chain.type}:${chain.id}`);
26
+ };
27
+ static resetCurrentChain = () => {
28
+ this.currentChain = undefined;
29
+ };
30
+ static removeAllObservers = () => {
31
+ for (const unsubscribe of this.currentSubscriptions ?? []) {
32
+ unsubscribe();
33
+ }
34
+ this.currentContentTopics = [];
35
+ this.currentSubscriptions = [];
36
+ };
37
+ static getDecodersForChain = (chain) => {
38
+ const contentTopicFees = contentTopics.fees(chain);
39
+ const contentTopicTransactResponse = contentTopics.transactResponse(chain);
40
+ const feesDecoder = createDecoder(contentTopicFees, WAKU_RAILGUN_PUB_SUB_TOPIC);
41
+ const transactResponseDecoder = createDecoder(contentTopicTransactResponse, WAKU_RAILGUN_PUB_SUB_TOPIC);
42
+ const feesCallback = (message) => handleBroadcasterFeesMessage(chain, message, contentTopicFees);
43
+ const transactResponseCallback = BroadcasterTransactResponse.handleBroadcasterTransactionResponseMessage;
44
+ const feesSubscriptionParams = {
45
+ topic: contentTopicFees,
46
+ decoder: feesDecoder,
47
+ callback: feesCallback,
48
+ };
49
+ const transactResponseSubscriptionParams = {
50
+ topic: contentTopicTransactResponse,
51
+ decoder: transactResponseDecoder,
52
+ callback: transactResponseCallback,
53
+ };
54
+ return [feesSubscriptionParams, transactResponseSubscriptionParams];
55
+ };
56
+ static subscribedPeers = [];
57
+ static addChainObservers = async (waku, chain) => {
58
+ if (!isDefined(waku.relay)) {
59
+ return;
60
+ }
61
+ await WakuObservers.addSubscriptions(chain, waku).catch(err => {
62
+ BroadcasterDebug.log(`Error adding Observers. ${err.message}`);
63
+ });
64
+ const currentContentTopics = WakuObservers.getCurrentContentTopics();
65
+ BroadcasterDebug.log('Waku content topics:');
66
+ for (const observer of currentContentTopics) {
67
+ BroadcasterDebug.log(observer);
68
+ }
69
+ };
70
+ static async addTransportSubscription(waku, topic, callback) {
71
+ if (!isDefined(waku)) {
72
+ BroadcasterDebug.log('No waku instance found, Transport Subscription not added.');
73
+ return;
74
+ }
75
+ const transportTopic = contentTopics.encrypted(topic);
76
+ const decoder = createDecoder(transportTopic, WAKU_RAILGUN_PUB_SUB_TOPIC);
77
+ const unsubscribe = await waku.relay.subscribe(decoder, callback);
78
+ this.currentSubscriptions.push(unsubscribe);
79
+ this.currentContentTopics.push(transportTopic);
80
+ }
81
+ static async addSubscriptions(chain, waku) {
82
+ if (!isDefined(chain) || !isDefined(waku)) {
83
+ BroadcasterDebug.log('AddSubscription: No Waku or Chain defined.');
84
+ return;
85
+ }
86
+ const subscriptionParams = WakuObservers.getDecodersForChain(chain);
87
+ const topics = subscriptionParams.map(subParam => subParam.topic);
88
+ const newTopics = topics.filter(topic => !this.currentContentTopics.includes(topic));
89
+ this.currentContentTopics.push(...newTopics);
90
+ this.currentSubscriptions ??= [];
91
+ for (const subParam of subscriptionParams) {
92
+ const { decoder, callback } = subParam;
93
+ const unsubscribe = await waku.relay.subscribe(decoder, callback);
94
+ this.currentSubscriptions.push(unsubscribe);
95
+ }
96
+ }
97
+ static getCurrentContentTopics(waku) {
98
+ return this.currentContentTopics;
99
+ }
100
+ }
101
+ //# sourceMappingURL=waku-observers.js.map
@@ -0,0 +1 @@
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 { createDecoder } from '@waku/core';\nimport { contentTopics } from './waku-topics.js';\nimport {\n IMessage,\n IFilterSubscription,\n IDecoder,\n RelayNode,\n Unsubscribe,\n} from '@waku/interfaces';\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_PUB_SUB_TOPIC } from '../models/constants.js';\n\ntype SubscriptionParams = {\n topic: string;\n decoder: IDecoder<any> | IDecoder<any>[];\n callback: (message: any) => void;\n};\n\nexport class WakuObservers {\n private static currentChain: Optional<Chain>;\n private static currentContentTopics: string[] = [];\n private static currentSubscriptions: Unsubscribe[] = [];\n static setObserversForChain = async (\n waku: Optional<RelayNode>,\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 WakuObservers.removeAllObservers();\n await WakuObservers.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 removeAllObservers = () => {\n for (const unsubscribe of this.currentSubscriptions ?? []) {\n unsubscribe();\n }\n this.currentContentTopics = [];\n this.currentSubscriptions = [];\n };\n\n private static getDecodersForChain = (chain: Chain) => {\n const contentTopicFees = contentTopics.fees(chain);\n const contentTopicTransactResponse = contentTopics.transactResponse(chain);\n const feesDecoder = createDecoder(\n contentTopicFees,\n WAKU_RAILGUN_PUB_SUB_TOPIC,\n );\n const transactResponseDecoder = createDecoder(\n contentTopicTransactResponse,\n WAKU_RAILGUN_PUB_SUB_TOPIC,\n );\n const feesCallback = (message: IMessage) =>\n handleBroadcasterFeesMessage(chain, message, contentTopicFees);\n const transactResponseCallback =\n BroadcasterTransactResponse.handleBroadcasterTransactionResponseMessage;\n\n const feesSubscriptionParams = {\n topic: contentTopicFees,\n decoder: feesDecoder,\n callback: feesCallback,\n };\n const transactResponseSubscriptionParams = {\n topic: contentTopicTransactResponse,\n decoder: transactResponseDecoder,\n callback: transactResponseCallback,\n };\n return [feesSubscriptionParams, transactResponseSubscriptionParams];\n };\n\n static subscribedPeers: string[] = [];\n\n private static addChainObservers = async (waku: RelayNode, chain: Chain) => {\n if (!isDefined(waku.relay)) {\n return;\n }\n\n await WakuObservers.addSubscriptions(chain, waku).catch(err => {\n BroadcasterDebug.log(`Error adding Observers. ${err.message}`);\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<RelayNode>,\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_PUB_SUB_TOPIC);\n const unsubscribe = await waku.relay.subscribe(decoder, callback);\n this.currentSubscriptions.push(unsubscribe);\n this.currentContentTopics.push(transportTopic);\n }\n\n private static async addSubscriptions(\n chain: Optional<Chain>,\n waku: Optional<RelayNode>,\n ) {\n if (!isDefined(chain) || !isDefined(waku)) {\n BroadcasterDebug.log('AddSubscription: No Waku or Chain defined.');\n return;\n }\n\n const subscriptionParams = WakuObservers.getDecodersForChain(chain);\n const topics = subscriptionParams.map(subParam => subParam.topic);\n const newTopics = topics.filter(\n topic => !this.currentContentTopics.includes(topic),\n );\n this.currentContentTopics.push(...newTopics);\n\n this.currentSubscriptions ??= [];\n for (const subParam of subscriptionParams) {\n const { decoder, callback } = subParam;\n const unsubscribe = await waku.relay.subscribe(decoder, callback);\n this.currentSubscriptions.push(unsubscribe);\n }\n }\n\n static getCurrentContentTopics(waku?: RelayNode): string[] {\n return this.currentContentTopics;\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import { Chain } from '@railgun-community/shared-models';
2
+ export declare const contentTopics: {
3
+ fees: (chain: Chain) => string;
4
+ encrypted: (topic: string) => string;
5
+ transact: (chain: Chain) => string;
6
+ transactResponse: (chain: Chain) => string;
7
+ };
@@ -0,0 +1,7 @@
1
+ export const contentTopics = {
2
+ fees: (chain) => `/railgun/v2/${chain.type}/${chain.id}/fees/json`,
3
+ encrypted: (topic) => `/railgun/v2/encrypted${topic}`,
4
+ transact: (chain) => `/railgun/v2/${chain.type}/${chain.id}/transact/json`,
5
+ transactResponse: (chain) => `/railgun/v2/${chain.type}/${chain.id}/transact-response/json`,
6
+ };
7
+ //# sourceMappingURL=waku-topics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waku-topics.js","sourceRoot":"","sources":["../../src/waku/waku-topics.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,CAAC,KAAY,EAAE,EAAE,CAAC,eAAe,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,YAAY;IACzE,SAAS,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,wBAAwB,KAAK,EAAE;IAC7D,QAAQ,EAAE,CAAC,KAAY,EAAE,EAAE,CACzB,eAAe,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,gBAAgB;IACvD,gBAAgB,EAAE,CAAC,KAAY,EAAE,EAAE,CACjC,eAAe,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,yBAAyB;CACjE,CAAC","sourcesContent":["import { Chain } from '@railgun-community/shared-models';\n\nexport const contentTopics = {\n fees: (chain: Chain) => `/railgun/v2/${chain.type}/${chain.id}/fees/json`,\n encrypted: (topic: string) => `/railgun/v2/encrypted${topic}`,\n transact: (chain: Chain) =>\n `/railgun/v2/${chain.type}/${chain.id}/transact/json`,\n transactResponse: (chain: Chain) =>\n `/railgun/v2/${chain.type}/${chain.id}/transact-response/json`,\n};\n"]}
@@ -0,0 +1,32 @@
1
+ import { Chain, SelectedBroadcaster } from '@railgun-community/shared-models';
2
+ import { BroadcasterConnectionStatusCallback, BroadcasterDebugger, BroadcasterOptions } from './models/export-models.js';
3
+ import { RelayNode } from '@waku/sdk';
4
+ export declare class WakuBroadcasterClient {
5
+ private static chain;
6
+ private static statusCallback;
7
+ private static started;
8
+ private static isRestarting;
9
+ static pollDelay: number;
10
+ static start(chain: Chain, broadcasterOptions: BroadcasterOptions, statusCallback: BroadcasterConnectionStatusCallback, broadcasterDebugger?: BroadcasterDebugger): Promise<void>;
11
+ static stop(): Promise<void>;
12
+ static isStarted(): boolean;
13
+ static setChain(chain: Chain): Promise<void>;
14
+ static getContentTopics(): string[];
15
+ static getMeshPeerCount(): number;
16
+ static getPubSubPeerCount(): number;
17
+ static getLightPushPeerCount(): Promise<number>;
18
+ static getFilterPeerCount(): Promise<number>;
19
+ static findBestBroadcaster(chain: Chain, tokenAddress: string, useRelayAdapt: boolean): Optional<SelectedBroadcaster>;
20
+ static findAllBroadcastersForChain(chain: Chain, useRelayAdapt: boolean): Optional<SelectedBroadcaster[]>;
21
+ static findRandomBroadcasterForToken(chain: Chain, tokenAddress: string, useRelayAdapt: boolean, percentageThreshold?: number): Optional<SelectedBroadcaster>;
22
+ static findBroadcastersForToken(chain: Chain, tokenAddress: string, useRelayAdapt: boolean): Optional<SelectedBroadcaster[]>;
23
+ static setAddressFilters(allowlist: Optional<string[]>, blocklist: Optional<string[]>): void;
24
+ static tryReconnect(): Promise<void>;
25
+ static supportsToken(chain: Chain, tokenAddress: string, useRelayAdapt: boolean): boolean;
26
+ private static restart;
27
+ private static pollStatus;
28
+ private static updateStatus;
29
+ static addTransportSubscription(waku: Optional<RelayNode>, topic: string, callback: (message: any) => void): Promise<void>;
30
+ static sendTransport(data: object, topic: string): void;
31
+ static getWakuCore(): Optional<RelayNode>;
32
+ }
@@ -0,0 +1,147 @@
1
+ import { delay, POI_REQUIRED_LISTS, BroadcasterConnectionStatus, } from '@railgun-community/shared-models';
2
+ import { BroadcasterFeeCache } from './fees/broadcaster-fee-cache.js';
3
+ import { AddressFilter } from './filters/address-filter.js';
4
+ import { BroadcasterSearch } from './search/best-broadcaster.js';
5
+ import { BroadcasterStatus } from './status/broadcaster-connection-status.js';
6
+ import { BroadcasterDebug } from './utils/broadcaster-debug.js';
7
+ import { WakuObservers } from './waku/waku-observers.js';
8
+ import { WakuBroadcasterWakuCore } from './waku/waku-broadcaster-waku-core.js';
9
+ import { contentTopics } from './waku/waku-topics.js';
10
+ export class WakuBroadcasterClient {
11
+ static chain;
12
+ static statusCallback;
13
+ static started = false;
14
+ static isRestarting = false;
15
+ static pollDelay = 10000;
16
+ static async start(chain, broadcasterOptions, statusCallback, broadcasterDebugger) {
17
+ this.chain = chain;
18
+ this.statusCallback = statusCallback;
19
+ WakuBroadcasterWakuCore.setBroadcasterOptions(broadcasterOptions);
20
+ if (broadcasterDebugger) {
21
+ BroadcasterDebug.setDebugger(broadcasterDebugger);
22
+ }
23
+ BroadcasterFeeCache.init(broadcasterOptions.poiActiveListKeys ??
24
+ POI_REQUIRED_LISTS.map(list => list.key));
25
+ try {
26
+ this.started = false;
27
+ await WakuBroadcasterWakuCore.initWaku(chain);
28
+ this.started = true;
29
+ this.pollStatus();
30
+ }
31
+ catch (cause) {
32
+ if (!(cause instanceof Error)) {
33
+ throw new Error('Unexpected non-error thrown', { cause });
34
+ }
35
+ throw new Error('Cannot connect to Broadcaster network.', { cause });
36
+ }
37
+ }
38
+ static async stop() {
39
+ await WakuBroadcasterWakuCore.disconnect(true);
40
+ this.started = false;
41
+ this.updateStatus();
42
+ }
43
+ static isStarted() {
44
+ return this.started;
45
+ }
46
+ static async setChain(chain) {
47
+ if (!WakuBroadcasterClient.started) {
48
+ return;
49
+ }
50
+ WakuBroadcasterClient.chain = chain;
51
+ await WakuObservers.setObserversForChain(WakuBroadcasterWakuCore.waku, chain);
52
+ WakuBroadcasterClient.updateStatus();
53
+ }
54
+ static getContentTopics() {
55
+ return WakuObservers.getCurrentContentTopics();
56
+ }
57
+ static getMeshPeerCount() {
58
+ return WakuBroadcasterWakuCore.getMeshPeerCount();
59
+ }
60
+ static getPubSubPeerCount() {
61
+ return WakuBroadcasterWakuCore.getPubSubPeerCount();
62
+ }
63
+ static async getLightPushPeerCount() {
64
+ return await WakuBroadcasterWakuCore.getLightPushPeerCount();
65
+ }
66
+ static async getFilterPeerCount() {
67
+ return await WakuBroadcasterWakuCore.getFilterPeerCount();
68
+ }
69
+ static findBestBroadcaster(chain, tokenAddress, useRelayAdapt) {
70
+ if (!WakuBroadcasterClient.started) {
71
+ return;
72
+ }
73
+ return BroadcasterSearch.findBestBroadcaster(chain, tokenAddress, useRelayAdapt);
74
+ }
75
+ static findAllBroadcastersForChain(chain, useRelayAdapt) {
76
+ if (!WakuBroadcasterClient.started) {
77
+ return [];
78
+ }
79
+ return BroadcasterSearch.findAllBroadcastersForChain(chain, useRelayAdapt);
80
+ }
81
+ static findRandomBroadcasterForToken(chain, tokenAddress, useRelayAdapt, percentageThreshold = 5) {
82
+ if (!WakuBroadcasterClient.started) {
83
+ return;
84
+ }
85
+ return BroadcasterSearch.findRandomBroadcasterForToken(chain, tokenAddress, useRelayAdapt, percentageThreshold);
86
+ }
87
+ static findBroadcastersForToken(chain, tokenAddress, useRelayAdapt) {
88
+ if (!WakuBroadcasterClient.started) {
89
+ return;
90
+ }
91
+ return BroadcasterSearch.findBroadcastersForToken(chain, tokenAddress, useRelayAdapt);
92
+ }
93
+ static setAddressFilters(allowlist, blocklist) {
94
+ AddressFilter.setAllowlist(allowlist);
95
+ AddressFilter.setBlocklist(blocklist);
96
+ }
97
+ static async tryReconnect() {
98
+ BroadcasterFeeCache.resetCache(WakuBroadcasterClient.chain);
99
+ WakuBroadcasterClient.updateStatus();
100
+ await WakuBroadcasterClient.restart();
101
+ }
102
+ static supportsToken(chain, tokenAddress, useRelayAdapt) {
103
+ return BroadcasterFeeCache.supportsToken(chain, tokenAddress, useRelayAdapt);
104
+ }
105
+ static async restart() {
106
+ if (this.isRestarting || !this.started) {
107
+ return;
108
+ }
109
+ this.isRestarting = true;
110
+ try {
111
+ BroadcasterDebug.log('Restarting Waku...');
112
+ await WakuBroadcasterWakuCore.reinitWaku(this.chain);
113
+ this.isRestarting = false;
114
+ }
115
+ catch (cause) {
116
+ this.isRestarting = false;
117
+ if (!(cause instanceof Error)) {
118
+ return;
119
+ }
120
+ BroadcasterDebug.error(new Error('Error reinitializing Waku Broadcaster Client', { cause }));
121
+ }
122
+ }
123
+ static async pollStatus() {
124
+ this.updateStatus();
125
+ await delay(WakuBroadcasterClient.pollDelay);
126
+ this.pollStatus();
127
+ }
128
+ static updateStatus() {
129
+ const status = BroadcasterStatus.getBroadcasterConnectionStatus(this.chain);
130
+ this.statusCallback(this.chain, status);
131
+ if (status === BroadcasterConnectionStatus.Disconnected ||
132
+ status === BroadcasterConnectionStatus.Error) {
133
+ this.restart();
134
+ }
135
+ }
136
+ static async addTransportSubscription(waku, topic, callback) {
137
+ await WakuObservers.addTransportSubscription(WakuBroadcasterWakuCore.waku, topic, callback);
138
+ }
139
+ static sendTransport(data, topic) {
140
+ const customTopic = contentTopics.encrypted(topic);
141
+ WakuBroadcasterWakuCore.relayMessage(data, customTopic);
142
+ }
143
+ static getWakuCore() {
144
+ return WakuBroadcasterWakuCore.waku;
145
+ }
146
+ }
147
+ //# sourceMappingURL=waku-broadcaster-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waku-broadcaster-client.js","sourceRoot":"","sources":["../src/waku-broadcaster-client.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Chain,\n delay,\n isDefined,\n POI_REQUIRED_LISTS,\n BroadcasterConnectionStatus,\n SelectedBroadcaster,\n} from '@railgun-community/shared-models';\nimport { BroadcasterFeeCache } from './fees/broadcaster-fee-cache.js';\nimport { AddressFilter } from './filters/address-filter.js';\nimport {\n BroadcasterConnectionStatusCallback,\n BroadcasterDebugger,\n BroadcasterOptions,\n} from './models/export-models.js';\nimport { BroadcasterSearch } from './search/best-broadcaster.js';\nimport { BroadcasterStatus } from './status/broadcaster-connection-status.js';\nimport { BroadcasterDebug } from './utils/broadcaster-debug.js';\nimport { WakuObservers } from './waku/waku-observers.js';\nimport { WakuBroadcasterWakuCore } from './waku/waku-broadcaster-waku-core.js';\nimport { RelayNode } from '@waku/sdk';\nimport { contentTopics } from './waku/waku-topics.js';\n\nexport class WakuBroadcasterClient {\n private static chain: Chain;\n private static statusCallback: BroadcasterConnectionStatusCallback;\n private static started = false;\n private static isRestarting = false;\n\n static pollDelay = 10000;\n\n static async start(\n chain: Chain,\n broadcasterOptions: BroadcasterOptions,\n statusCallback: BroadcasterConnectionStatusCallback,\n broadcasterDebugger?: BroadcasterDebugger,\n ) {\n this.chain = chain;\n this.statusCallback = statusCallback;\n\n WakuBroadcasterWakuCore.setBroadcasterOptions(broadcasterOptions);\n\n if (broadcasterDebugger) {\n BroadcasterDebug.setDebugger(broadcasterDebugger);\n }\n\n BroadcasterFeeCache.init(\n broadcasterOptions.poiActiveListKeys ??\n POI_REQUIRED_LISTS.map(list => list.key),\n );\n\n try {\n this.started = false;\n await WakuBroadcasterWakuCore.initWaku(chain);\n this.started = true;\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.pollStatus();\n } catch (cause) {\n if (!(cause instanceof Error)) {\n throw new Error('Unexpected non-error thrown', { cause });\n }\n throw new Error('Cannot connect to Broadcaster network.', { cause });\n }\n }\n\n static async stop() {\n await WakuBroadcasterWakuCore.disconnect(true);\n this.started = false;\n this.updateStatus();\n }\n\n static isStarted() {\n return this.started;\n }\n\n static async setChain(chain: Chain): Promise<void> {\n if (!WakuBroadcasterClient.started) {\n return;\n }\n\n WakuBroadcasterClient.chain = chain;\n await WakuObservers.setObserversForChain(\n WakuBroadcasterWakuCore.waku,\n chain,\n );\n WakuBroadcasterClient.updateStatus();\n }\n\n static getContentTopics(): string[] {\n return WakuObservers.getCurrentContentTopics();\n }\n\n static getMeshPeerCount(): number {\n return WakuBroadcasterWakuCore.getMeshPeerCount();\n }\n\n static getPubSubPeerCount(): number {\n return WakuBroadcasterWakuCore.getPubSubPeerCount();\n }\n\n static async getLightPushPeerCount(): Promise<number> {\n return await WakuBroadcasterWakuCore.getLightPushPeerCount();\n }\n\n static async getFilterPeerCount(): Promise<number> {\n return await WakuBroadcasterWakuCore.getFilterPeerCount();\n }\n /**\n * The function `findBestBroadcaster` finds the broadcaster with the lowest fees for a given chain and token.\n * @param {Chain} chain - The `chain` parameter is a Chain object that represents the network to find a broadcaster for.\n * @param {string} tokenAddress - The `tokenAddress` parameter is a string that represents the\n * address of an ERC20 Token on the network, a broadcaster broadcasting fees for this token will be selected.\n * @param {boolean} useRelayAdapt - A boolean value indicating whether to select broadcasters that\n * support RelayAdapt transactions.\n * @returns an Optional<SelectedBroadcaster> object.\n */\n static findBestBroadcaster(\n chain: Chain,\n tokenAddress: string,\n useRelayAdapt: boolean,\n ): Optional<SelectedBroadcaster> {\n if (!WakuBroadcasterClient.started) {\n return;\n }\n\n return BroadcasterSearch.findBestBroadcaster(\n chain,\n tokenAddress,\n useRelayAdapt,\n );\n }\n\n /**\n * The function `findAllBroadcastersForChain` returns an array of all available broadcasters fee-tokens for a given chain.\n * @param {Chain} chain - The `chain` parameter is a Chain object that represents the network to find all broadcasters for.\n * @param {boolean} useRelayAdapt - A boolean value indicating whether to select broadcasters that\n * support RelayAdapt transactions.\n * @returns an Optional<SelectedBroadcaster[]> object.\n */\n static findAllBroadcastersForChain(\n chain: Chain,\n useRelayAdapt: boolean,\n ): Optional<SelectedBroadcaster[]> {\n if (!WakuBroadcasterClient.started) {\n return [];\n }\n\n return BroadcasterSearch.findAllBroadcastersForChain(chain, useRelayAdapt);\n }\n\n /**\n * The function `findRandomBroadcasterForToken` selects a random broadcaster from a list of broadcasters that is based on\n * their fees for a specific token, and how much higher their fees are compared to the broadcaster with\n * the lowest fees.\n * @param {Chain} chain - The `chain` parameter is a Chain object that represents the network to find a broadcaster for.\n * @param {string} tokenAddress - The `tokenAddress` parameter is a string that represents the\n * address of an ERC20 Token on the network, a broadcaster broadcasting fees for this token will be selected.\n * @param {boolean} useRelayAdapt - A boolean value indicating whether to select broadcasters that\n * support RelayAdapt transactions.\n * @param {number} [percentageThreshold=5] - The `percentageThreshold` parameter is a number that\n * represents the maximum percentage increase in fees that a broadcaster can have compared to the broadcaster\n * with the lowest fees. For example, if the `percentageThreshold` is set to 5, it means that a\n * broadcaster can have a maximum of 5% higher fees than the broadcaster with the lowest fees and still be selected.\n * Defaults to 5.\n * @returns an Optional<SelectedBroadcaster> object.\n */\n static findRandomBroadcasterForToken(\n chain: Chain,\n tokenAddress: string,\n useRelayAdapt: boolean,\n percentageThreshold: number = 5,\n ): Optional<SelectedBroadcaster> {\n if (!WakuBroadcasterClient.started) {\n return;\n }\n\n return BroadcasterSearch.findRandomBroadcasterForToken(\n chain,\n tokenAddress,\n useRelayAdapt,\n percentageThreshold,\n );\n }\n\n /**\n * The function `findBroadcastersForToken` takes in a chain, token address, and a boolean flag, and\n * returns an array of selected broadcasters based on the provided parameters.\n * @param {Chain} chain - The `chain` parameter is a Chain object that represents the network to find a broadcaster for.\n * @param {string} tokenAddress - The `tokenAddress` parameter is a string that represents the\n * address of an ERC20 Token on the network; a broadcaster broadcasting fees for this token will be selected.\n * @param {boolean} useRelayAdapt - A boolean value indicating whether to select broadcasters that\n * support RelayAdapt transactions.\n * @returns an Optional<SelectedBroadcaster[]> object.\n */\n static findBroadcastersForToken(\n chain: Chain,\n tokenAddress: string,\n useRelayAdapt: boolean,\n ): Optional<SelectedBroadcaster[]> {\n if (!WakuBroadcasterClient.started) {\n return;\n }\n\n return BroadcasterSearch.findBroadcastersForToken(\n chain,\n tokenAddress,\n useRelayAdapt,\n );\n }\n\n static setAddressFilters(\n allowlist: Optional<string[]>,\n blocklist: Optional<string[]>,\n ): void {\n AddressFilter.setAllowlist(allowlist);\n AddressFilter.setBlocklist(blocklist);\n }\n\n static async tryReconnect(): Promise<void> {\n // Reset fees, which will reset status to \"Searching\".\n BroadcasterFeeCache.resetCache(WakuBroadcasterClient.chain);\n WakuBroadcasterClient.updateStatus();\n\n await WakuBroadcasterClient.restart();\n }\n\n static supportsToken(\n chain: Chain,\n tokenAddress: string,\n useRelayAdapt: boolean,\n ) {\n return BroadcasterFeeCache.supportsToken(\n chain,\n tokenAddress,\n useRelayAdapt,\n );\n }\n\n private static async restart(): Promise<void> {\n if (this.isRestarting || !this.started) {\n return;\n }\n this.isRestarting = true;\n try {\n BroadcasterDebug.log('Restarting Waku...');\n await WakuBroadcasterWakuCore.reinitWaku(this.chain);\n this.isRestarting = false;\n } catch (cause) {\n this.isRestarting = false;\n if (!(cause instanceof Error)) {\n return;\n }\n BroadcasterDebug.error(\n new Error('Error reinitializing Waku Broadcaster Client', { cause }),\n );\n }\n }\n\n /**\n * Start keep-alive poller which checks Broadcaster status every few seconds.\n */\n private static async pollStatus(): Promise<void> {\n this.updateStatus();\n\n await delay(WakuBroadcasterClient.pollDelay);\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.pollStatus();\n }\n\n private static updateStatus() {\n const status = BroadcasterStatus.getBroadcasterConnectionStatus(this.chain);\n\n this.statusCallback(this.chain, status);\n\n if (\n status === BroadcasterConnectionStatus.Disconnected ||\n status === BroadcasterConnectionStatus.Error\n ) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.restart();\n }\n }\n // Waku Transport functions\n static async addTransportSubscription(\n waku: Optional<RelayNode>,\n topic: string,\n callback: (message: any) => void,\n ): Promise<void> {\n await WakuObservers.addTransportSubscription(\n WakuBroadcasterWakuCore.waku,\n topic,\n callback,\n );\n }\n\n static sendTransport(data: object, topic: string): void {\n const customTopic = contentTopics.encrypted(topic);\n WakuBroadcasterWakuCore.relayMessage(data, customTopic);\n }\n\n static getWakuCore(): Optional<RelayNode> {\n return WakuBroadcasterWakuCore.waku;\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@railgun-community/waku-broadcaster-client-web",
3
+ "version": "7.0.0",
4
+ "license": "MIT",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "files": [
8
+ "dist/**/*"
9
+ ],
10
+ "exports": {
11
+ ".": "./dist/index.js"
12
+ },
13
+ "scripts": {
14
+ "clean": "rm -rf dist",
15
+ "build": "npm run clean && tsc",
16
+ "check-circular-deps": "madge --circular .",
17
+ "eslint": "eslint src --ext .ts,.tsx --fix",
18
+ "lint": "npm run check-circular-deps && npm run eslint && tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
19
+ "tsc-test": "tsc -p tsconfig.test.json && tsc-alias -p tsconfig.test.json",
20
+ "compile-test": "npm run clean && npm run tsc-test",
21
+ "test-coverage": "npm run compile-test && c8 mocha",
22
+ "test": "npm run compile-test && NODE_ENV=test mocha 'dist/**/*.test.js'"
23
+ },
24
+ "dependencies": {
25
+ "@libp2p/bootstrap": "^10.0.11",
26
+ "@waku/core": "0.0.27",
27
+ "@waku/relay": "0.0.10",
28
+ "@waku/sdk": "0.0.23",
29
+ "@waku/interfaces": "0.0.22",
30
+ "libp2p": "^1.1.2"
31
+ },
32
+ "peerDependencies": {
33
+ "@railgun-community/shared-models": "7.0.x",
34
+ "@railgun-community/wallet": "8.1.x",
35
+ "ethers": "github:Railgun-Community/ethers.js#v6.7.10"
36
+ },
37
+ "devDependencies": {
38
+ "@railgun-community/shared-models": "7.0.x",
39
+ "@railgun-community/wallet": "8.1.x",
40
+ "ethers": "github:Railgun-Community/ethers.js#v6.7.10",
41
+ "@types/chai": "^4.3.5",
42
+ "@types/chai-as-promised": "^7.1.5",
43
+ "@types/leveldown": "^4.0.3",
44
+ "@types/mocha": "^10.0.1",
45
+ "@types/node": "^20.4.2",
46
+ "@types/sinon": "^10.0.15",
47
+ "@typescript-eslint/eslint-plugin": "^6.1.0",
48
+ "@typescript-eslint/parser": "^6.1.0",
49
+ "c8": "^8.0.0",
50
+ "chai": "^4.3.7",
51
+ "chai-as-promised": "^7.1.1",
52
+ "eslint": "^8.45.0",
53
+ "eslint-config-prettier": "^8.8.0",
54
+ "eslint-plugin-flowtype": "^8.0.3",
55
+ "eslint-plugin-import": "^2.27.5",
56
+ "leveldown": "^6.1.1",
57
+ "madge": "^6.1.0",
58
+ "mocha": "^10.2.0",
59
+ "prettier": "^3.0.0",
60
+ "sinon": "^15.2.0",
61
+ "ts-node": "^10.9.1",
62
+ "tsc-alias": "^1.8.7",
63
+ "typescript": "^5.1.6"
64
+ }
65
+ }