@streamr/node 100.0.0-rc.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 (238) hide show
  1. package/LICENSE +78 -0
  2. package/README.md +54 -0
  3. package/bin/broker.ts +36 -0
  4. package/bin/config-wizard.js +4 -0
  5. package/bin/config-wizard.ts +17 -0
  6. package/bin/delete-expired-data.ts +41 -0
  7. package/bin/entry-point.ts +27 -0
  8. package/configs/development-1.env.json +68 -0
  9. package/configs/development-2.env.json +53 -0
  10. package/configs/development-3.env.json +53 -0
  11. package/configs/development-prod-resend.env.json +21 -0
  12. package/configs/docker-1.env.json +72 -0
  13. package/configs/docker-2.env.json +58 -0
  14. package/configs/docker-3.env.json +58 -0
  15. package/configuration.md +38 -0
  16. package/dist/bin/broker.d.ts +2 -0
  17. package/dist/bin/broker.js +42 -0
  18. package/dist/bin/broker.js.map +1 -0
  19. package/dist/bin/config-wizard.d.ts +2 -0
  20. package/dist/bin/config-wizard.js +22 -0
  21. package/dist/bin/config-wizard.js.map +1 -0
  22. package/dist/bin/delete-expired-data.d.ts +2 -0
  23. package/dist/bin/delete-expired-data.js +44 -0
  24. package/dist/bin/delete-expired-data.js.map +1 -0
  25. package/dist/bin/entry-point.d.ts +2 -0
  26. package/dist/bin/entry-point.js +28 -0
  27. package/dist/bin/entry-point.js.map +1 -0
  28. package/dist/package.json +78 -0
  29. package/dist/src/Plugin.d.ts +33 -0
  30. package/dist/src/Plugin.js +43 -0
  31. package/dist/src/Plugin.js.map +1 -0
  32. package/dist/src/apiAuthentication.d.ts +4 -0
  33. package/dist/src/apiAuthentication.js +16 -0
  34. package/dist/src/apiAuthentication.js.map +1 -0
  35. package/dist/src/broker.d.ts +8 -0
  36. package/dist/src/broker.js +69 -0
  37. package/dist/src/broker.js.map +1 -0
  38. package/dist/src/config/ConfigWizard.d.ts +5 -0
  39. package/dist/src/config/ConfigWizard.js +466 -0
  40. package/dist/src/config/ConfigWizard.js.map +1 -0
  41. package/dist/src/config/config.d.ts +26 -0
  42. package/dist/src/config/config.js +92 -0
  43. package/dist/src/config/config.js.map +1 -0
  44. package/dist/src/config/config.schema.json +86 -0
  45. package/dist/src/config/definitions.schema.json +35 -0
  46. package/dist/src/config/migration.d.ts +6 -0
  47. package/dist/src/config/migration.js +210 -0
  48. package/dist/src/config/migration.js.map +1 -0
  49. package/dist/src/config/validateConfig.d.ts +4 -0
  50. package/dist/src/config/validateConfig.js +40 -0
  51. package/dist/src/config/validateConfig.js.map +1 -0
  52. package/dist/src/exports.d.ts +3 -0
  53. package/dist/src/exports.js +6 -0
  54. package/dist/src/exports.js.map +1 -0
  55. package/dist/src/helpers/PayloadFormat.d.ts +19 -0
  56. package/dist/src/helpers/PayloadFormat.js +85 -0
  57. package/dist/src/helpers/PayloadFormat.js.map +1 -0
  58. package/dist/src/helpers/applyPluginClientConfigs.d.ts +3 -0
  59. package/dist/src/helpers/applyPluginClientConfigs.js +29 -0
  60. package/dist/src/helpers/applyPluginClientConfigs.js.map +1 -0
  61. package/dist/src/helpers/fetchOrThrow.d.ts +2 -0
  62. package/dist/src/helpers/fetchOrThrow.js +20 -0
  63. package/dist/src/helpers/fetchOrThrow.js.map +1 -0
  64. package/dist/src/helpers/generateMnemonicFromAddress.d.ts +5 -0
  65. package/dist/src/helpers/generateMnemonicFromAddress.js +16 -0
  66. package/dist/src/helpers/generateMnemonicFromAddress.js.map +1 -0
  67. package/dist/src/helpers/multiply.d.ts +1 -0
  68. package/dist/src/helpers/multiply.js +10 -0
  69. package/dist/src/helpers/multiply.js.map +1 -0
  70. package/dist/src/helpers/parser.d.ts +9 -0
  71. package/dist/src/helpers/parser.js +62 -0
  72. package/dist/src/helpers/parser.js.map +1 -0
  73. package/dist/src/helpers/partitions.d.ts +8 -0
  74. package/dist/src/helpers/partitions.js +32 -0
  75. package/dist/src/helpers/partitions.js.map +1 -0
  76. package/dist/src/helpers/weightedSample.d.ts +16 -0
  77. package/dist/src/helpers/weightedSample.js +35 -0
  78. package/dist/src/helpers/weightedSample.js.map +1 -0
  79. package/dist/src/httpServer.d.ts +16 -0
  80. package/dist/src/httpServer.js +71 -0
  81. package/dist/src/httpServer.js.map +1 -0
  82. package/dist/src/pluginRegistry.d.ts +3 -0
  83. package/dist/src/pluginRegistry.js +35 -0
  84. package/dist/src/pluginRegistry.js.map +1 -0
  85. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.d.ts +12 -0
  86. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js +36 -0
  87. package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js.map +1 -0
  88. package/dist/src/plugins/consoleMetrics/config.schema.json +18 -0
  89. package/dist/src/plugins/http/HttpPlugin.d.ts +8 -0
  90. package/dist/src/plugins/http/HttpPlugin.js +23 -0
  91. package/dist/src/plugins/http/HttpPlugin.js.map +1 -0
  92. package/dist/src/plugins/http/config.schema.json +12 -0
  93. package/dist/src/plugins/http/publishEndpoint.d.ts +3 -0
  94. package/dist/src/plugins/http/publishEndpoint.js +72 -0
  95. package/dist/src/plugins/http/publishEndpoint.js.map +1 -0
  96. package/dist/src/plugins/info/InfoPlugin.d.ts +9 -0
  97. package/dist/src/plugins/info/InfoPlugin.js +31 -0
  98. package/dist/src/plugins/info/InfoPlugin.js.map +1 -0
  99. package/dist/src/plugins/info/config.schema.json +12 -0
  100. package/dist/src/plugins/mqtt/Bridge.d.ts +40 -0
  101. package/dist/src/plugins/mqtt/Bridge.js +136 -0
  102. package/dist/src/plugins/mqtt/Bridge.js.map +1 -0
  103. package/dist/src/plugins/mqtt/MqttPlugin.d.ts +14 -0
  104. package/dist/src/plugins/mqtt/MqttPlugin.js +30 -0
  105. package/dist/src/plugins/mqtt/MqttPlugin.js.map +1 -0
  106. package/dist/src/plugins/mqtt/MqttServer.d.ts +22 -0
  107. package/dist/src/plugins/mqtt/MqttServer.js +109 -0
  108. package/dist/src/plugins/mqtt/MqttServer.js.map +1 -0
  109. package/dist/src/plugins/mqtt/config.schema.json +26 -0
  110. package/dist/src/plugins/operator/ConsistentHashRing.d.ts +20 -0
  111. package/dist/src/plugins/operator/ConsistentHashRing.js +64 -0
  112. package/dist/src/plugins/operator/ConsistentHashRing.js.map +1 -0
  113. package/dist/src/plugins/operator/ContractFacade.d.ts +80 -0
  114. package/dist/src/plugins/operator/ContractFacade.js +364 -0
  115. package/dist/src/plugins/operator/ContractFacade.js.map +1 -0
  116. package/dist/src/plugins/operator/MaintainTopologyHelper.d.ts +23 -0
  117. package/dist/src/plugins/operator/MaintainTopologyHelper.js +75 -0
  118. package/dist/src/plugins/operator/MaintainTopologyHelper.js.map +1 -0
  119. package/dist/src/plugins/operator/MaintainTopologyService.d.ts +11 -0
  120. package/dist/src/plugins/operator/MaintainTopologyService.js +57 -0
  121. package/dist/src/plugins/operator/MaintainTopologyService.js.map +1 -0
  122. package/dist/src/plugins/operator/OperatorFleetState.d.ts +33 -0
  123. package/dist/src/plugins/operator/OperatorFleetState.js +112 -0
  124. package/dist/src/plugins/operator/OperatorFleetState.js.map +1 -0
  125. package/dist/src/plugins/operator/OperatorPlugin.d.ts +50 -0
  126. package/dist/src/plugins/operator/OperatorPlugin.js +159 -0
  127. package/dist/src/plugins/operator/OperatorPlugin.js.map +1 -0
  128. package/dist/src/plugins/operator/StreamPartAssignments.d.ts +28 -0
  129. package/dist/src/plugins/operator/StreamPartAssignments.js +104 -0
  130. package/dist/src/plugins/operator/StreamPartAssignments.js.map +1 -0
  131. package/dist/src/plugins/operator/announceNodeToContract.d.ts +3 -0
  132. package/dist/src/plugins/operator/announceNodeToContract.js +39 -0
  133. package/dist/src/plugins/operator/announceNodeToContract.js.map +1 -0
  134. package/dist/src/plugins/operator/announceNodeToStream.d.ts +3 -0
  135. package/dist/src/plugins/operator/announceNodeToStream.js +25 -0
  136. package/dist/src/plugins/operator/announceNodeToStream.js.map +1 -0
  137. package/dist/src/plugins/operator/checkOperatorValueBreach.d.ts +2 -0
  138. package/dist/src/plugins/operator/checkOperatorValueBreach.js +21 -0
  139. package/dist/src/plugins/operator/checkOperatorValueBreach.js.map +1 -0
  140. package/dist/src/plugins/operator/closeExpiredFlags.d.ts +3 -0
  141. package/dist/src/plugins/operator/closeExpiredFlags.js +24 -0
  142. package/dist/src/plugins/operator/closeExpiredFlags.js.map +1 -0
  143. package/dist/src/plugins/operator/config.schema.json +152 -0
  144. package/dist/src/plugins/operator/createIsLeaderFn.d.ts +4 -0
  145. package/dist/src/plugins/operator/createIsLeaderFn.js +14 -0
  146. package/dist/src/plugins/operator/createIsLeaderFn.js.map +1 -0
  147. package/dist/src/plugins/operator/fetchRedundancyFactor.d.ts +2 -0
  148. package/dist/src/plugins/operator/fetchRedundancyFactor.js +43 -0
  149. package/dist/src/plugins/operator/fetchRedundancyFactor.js.map +1 -0
  150. package/dist/src/plugins/operator/formCoordinationStreamId.d.ts +3 -0
  151. package/dist/src/plugins/operator/formCoordinationStreamId.js +9 -0
  152. package/dist/src/plugins/operator/formCoordinationStreamId.js.map +1 -0
  153. package/dist/src/plugins/operator/heartbeatUtils.d.ts +67 -0
  154. package/dist/src/plugins/operator/heartbeatUtils.js +26 -0
  155. package/dist/src/plugins/operator/heartbeatUtils.js.map +1 -0
  156. package/dist/src/plugins/operator/inspectOverTime.d.ts +22 -0
  157. package/dist/src/plugins/operator/inspectOverTime.js +146 -0
  158. package/dist/src/plugins/operator/inspectOverTime.js.map +1 -0
  159. package/dist/src/plugins/operator/inspectRandomNode.d.ts +8 -0
  160. package/dist/src/plugins/operator/inspectRandomNode.js +44 -0
  161. package/dist/src/plugins/operator/inspectRandomNode.js.map +1 -0
  162. package/dist/src/plugins/operator/inspectionUtils.d.ts +23 -0
  163. package/dist/src/plugins/operator/inspectionUtils.js +120 -0
  164. package/dist/src/plugins/operator/inspectionUtils.js.map +1 -0
  165. package/dist/src/plugins/operator/maintainOperatorValue.d.ts +2 -0
  166. package/dist/src/plugins/operator/maintainOperatorValue.js +21 -0
  167. package/dist/src/plugins/operator/maintainOperatorValue.js.map +1 -0
  168. package/dist/src/plugins/operator/reviewSuspectNode.d.ts +24 -0
  169. package/dist/src/plugins/operator/reviewSuspectNode.js +56 -0
  170. package/dist/src/plugins/operator/reviewSuspectNode.js.map +1 -0
  171. package/dist/src/plugins/storage/Batch.d.ts +51 -0
  172. package/dist/src/plugins/storage/Batch.js +121 -0
  173. package/dist/src/plugins/storage/Batch.js.map +1 -0
  174. package/dist/src/plugins/storage/BatchManager.d.ts +27 -0
  175. package/dist/src/plugins/storage/BatchManager.js +117 -0
  176. package/dist/src/plugins/storage/BatchManager.js.map +1 -0
  177. package/dist/src/plugins/storage/Bucket.d.ts +23 -0
  178. package/dist/src/plugins/storage/Bucket.js +90 -0
  179. package/dist/src/plugins/storage/Bucket.js.map +1 -0
  180. package/dist/src/plugins/storage/BucketManager.d.ts +56 -0
  181. package/dist/src/plugins/storage/BucketManager.js +306 -0
  182. package/dist/src/plugins/storage/BucketManager.js.map +1 -0
  183. package/dist/src/plugins/storage/DataQueryFormat.d.ts +10 -0
  184. package/dist/src/plugins/storage/DataQueryFormat.js +51 -0
  185. package/dist/src/plugins/storage/DataQueryFormat.js.map +1 -0
  186. package/dist/src/plugins/storage/DeleteExpiredCmd.d.ts +28 -0
  187. package/dist/src/plugins/storage/DeleteExpiredCmd.js +155 -0
  188. package/dist/src/plugins/storage/DeleteExpiredCmd.js.map +1 -0
  189. package/dist/src/plugins/storage/SetMembershipSynchronizer.d.ts +33 -0
  190. package/dist/src/plugins/storage/SetMembershipSynchronizer.js +102 -0
  191. package/dist/src/plugins/storage/SetMembershipSynchronizer.js.map +1 -0
  192. package/dist/src/plugins/storage/Storage.d.ts +47 -0
  193. package/dist/src/plugins/storage/Storage.js +459 -0
  194. package/dist/src/plugins/storage/Storage.js.map +1 -0
  195. package/dist/src/plugins/storage/StorageConfig.d.ts +43 -0
  196. package/dist/src/plugins/storage/StorageConfig.js +83 -0
  197. package/dist/src/plugins/storage/StorageConfig.js.map +1 -0
  198. package/dist/src/plugins/storage/StorageEventListener.d.ts +17 -0
  199. package/dist/src/plugins/storage/StorageEventListener.js +46 -0
  200. package/dist/src/plugins/storage/StorageEventListener.js.map +1 -0
  201. package/dist/src/plugins/storage/StoragePlugin.d.ts +32 -0
  202. package/dist/src/plugins/storage/StoragePlugin.js +103 -0
  203. package/dist/src/plugins/storage/StoragePlugin.js.map +1 -0
  204. package/dist/src/plugins/storage/StoragePoller.d.ts +15 -0
  205. package/dist/src/plugins/storage/StoragePoller.js +47 -0
  206. package/dist/src/plugins/storage/StoragePoller.js.map +1 -0
  207. package/dist/src/plugins/storage/config.schema.json +88 -0
  208. package/dist/src/plugins/storage/dataMetadataEndpoint.d.ts +3 -0
  209. package/dist/src/plugins/storage/dataMetadataEndpoint.js +35 -0
  210. package/dist/src/plugins/storage/dataMetadataEndpoint.js.map +1 -0
  211. package/dist/src/plugins/storage/dataQueryEndpoint.d.ts +6 -0
  212. package/dist/src/plugins/storage/dataQueryEndpoint.js +181 -0
  213. package/dist/src/plugins/storage/dataQueryEndpoint.js.map +1 -0
  214. package/dist/src/plugins/storage/storageConfigEndpoint.d.ts +3 -0
  215. package/dist/src/plugins/storage/storageConfigEndpoint.js +31 -0
  216. package/dist/src/plugins/storage/storageConfigEndpoint.js.map +1 -0
  217. package/dist/src/plugins/subscriber/SubscriberPlugin.d.ts +16 -0
  218. package/dist/src/plugins/subscriber/SubscriberPlugin.js +22 -0
  219. package/dist/src/plugins/subscriber/SubscriberPlugin.js.map +1 -0
  220. package/dist/src/plugins/subscriber/config.schema.json +31 -0
  221. package/dist/src/plugins/websocket/Connection.d.ts +9 -0
  222. package/dist/src/plugins/websocket/Connection.js +45 -0
  223. package/dist/src/plugins/websocket/Connection.js.map +1 -0
  224. package/dist/src/plugins/websocket/PublishConnection.d.ts +12 -0
  225. package/dist/src/plugins/websocket/PublishConnection.js +46 -0
  226. package/dist/src/plugins/websocket/PublishConnection.js.map +1 -0
  227. package/dist/src/plugins/websocket/SubscribeConnection.d.ts +13 -0
  228. package/dist/src/plugins/websocket/SubscribeConnection.js +50 -0
  229. package/dist/src/plugins/websocket/SubscribeConnection.js.map +1 -0
  230. package/dist/src/plugins/websocket/WebsocketPlugin.d.ts +19 -0
  231. package/dist/src/plugins/websocket/WebsocketPlugin.js +26 -0
  232. package/dist/src/plugins/websocket/WebsocketPlugin.js.map +1 -0
  233. package/dist/src/plugins/websocket/WebsocketServer.d.ts +16 -0
  234. package/dist/src/plugins/websocket/WebsocketServer.js +132 -0
  235. package/dist/src/plugins/websocket/WebsocketServer.js.map +1 -0
  236. package/dist/src/plugins/websocket/config.schema.json +51 -0
  237. package/package.json +78 -0
  238. package/plugins.md +318 -0
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Bridge = void 0;
7
+ const protocol_1 = require("@streamr/protocol");
8
+ const utils_1 = require("@streamr/utils");
9
+ const without_1 = __importDefault(require("lodash/without"));
10
+ const parser_1 = require("../../helpers/parser");
11
+ const partitions_1 = require("../../helpers/partitions");
12
+ const DEFAULT_PARTITION = 0;
13
+ const logger = new utils_1.Logger(module);
14
+ const createMessageChainKey = (message) => {
15
+ const DELIMITER = '-';
16
+ return [message.streamId, message.streamPartition, message.publisherId, message.msgChainId].join(DELIMITER);
17
+ };
18
+ class Bridge {
19
+ streamrClient;
20
+ mqttServer;
21
+ payloadFormat;
22
+ streamIdDomain;
23
+ subscriptions = [];
24
+ publishMessageChains = new Set();
25
+ constructor(streamrClient, mqttServer, payloadFormat, streamIdDomain) {
26
+ this.streamrClient = streamrClient;
27
+ this.mqttServer = mqttServer;
28
+ this.payloadFormat = payloadFormat;
29
+ this.streamIdDomain = streamIdDomain;
30
+ }
31
+ async onMessageReceived(topic, payload, clientId) {
32
+ let message;
33
+ let streamPart;
34
+ try {
35
+ message = this.payloadFormat.createMessage(payload);
36
+ streamPart = this.getPublishStreamPart(topic);
37
+ }
38
+ catch (err) {
39
+ logger.warn('Unable to form message', { err, topic, clientId });
40
+ return;
41
+ }
42
+ const { content, metadata } = message;
43
+ try {
44
+ const publishedMessage = await this.streamrClient.publish({
45
+ id: streamPart.streamId,
46
+ partition: streamPart.partition
47
+ }, content, {
48
+ timestamp: metadata.timestamp,
49
+ partitionKey: (0, partitions_1.getPartitionKey)(content, streamPart),
50
+ msgChainId: clientId
51
+ });
52
+ this.publishMessageChains.add(createMessageChainKey(publishedMessage));
53
+ }
54
+ catch (err) {
55
+ logger.warn('Unable to publish message', { err, topic, clientId });
56
+ }
57
+ }
58
+ async onSubscribed(topic, clientId) {
59
+ logger.info('Handle client subscribe', { clientId, topic });
60
+ const streamPart = this.getSubscribeStreamPart(topic);
61
+ const existingSubscription = this.getSubscription(streamPart);
62
+ if (existingSubscription === undefined) {
63
+ const streamrClientSubscription = await this.streamrClient.subscribe(streamPart, (content, metadata) => {
64
+ if (!this.isSelfPublishedMessage(metadata)) {
65
+ const payload = this.payloadFormat.createPayload(content, metadata);
66
+ this.mqttServer.publish(topic, payload);
67
+ }
68
+ });
69
+ this.subscriptions.push({
70
+ streamrClientSubscription,
71
+ clientIds: [clientId]
72
+ });
73
+ }
74
+ else {
75
+ existingSubscription.clientIds.push(clientId);
76
+ }
77
+ }
78
+ /**
79
+ *
80
+ * If a stream is subscribed with a MQTT client and also published with same or another
81
+ * MQTT client, the message could be delivered to the subscribed client two
82
+ * ways:
83
+ *
84
+ * 1) automatic mirroring by Aedes (delivers all published messages to all subscribers)
85
+ * 2) via network node: the subscribing MQTT client receives the published message from the
86
+ * network node as it subscribes to the stream (by calling streamrClient.subscribe)
87
+ *
88
+ * The message should be delivered to the subscribed client only once. Theferore we filter
89
+ * out the "via network node" case by checking whether the message is one of the messages
90
+ * which the Bridge published to the network node.
91
+ *
92
+ * Each publishing session of a stream yields to a unique MessageChainKey value. We store that
93
+ * key value when we call streamrClient.publish().
94
+ *
95
+ * Here we simply check if the incoming message belongs to one of the publish chains. If it
96
+ * does, it must have been published by this Bridge.
97
+ */
98
+ isSelfPublishedMessage(message) {
99
+ const messageChainKey = createMessageChainKey(message);
100
+ return this.publishMessageChains.has(messageChainKey);
101
+ }
102
+ onUnsubscribed(topic, clientId) {
103
+ logger.info('Handle client unsubscribe', { clientId, topic });
104
+ const streamPart = this.getSubscribeStreamPart(topic);
105
+ const existingSubscription = this.getSubscription(streamPart);
106
+ if (existingSubscription !== undefined) {
107
+ existingSubscription.clientIds = (0, without_1.default)(existingSubscription.clientIds, clientId);
108
+ if (existingSubscription.clientIds.length === 0) {
109
+ existingSubscription.streamrClientSubscription.unsubscribe();
110
+ this.subscriptions = (0, without_1.default)(this.subscriptions, existingSubscription);
111
+ }
112
+ }
113
+ }
114
+ getSubscribeStreamPart(topic) {
115
+ const { base, query } = (0, parser_1.parseQueryAndBase)(topic);
116
+ const partition = (0, parser_1.parseQueryParameter)('partition', query, parser_1.parsePositiveInteger);
117
+ return (0, protocol_1.toStreamPartID)(this.getStreamId(base), partition ?? DEFAULT_PARTITION);
118
+ }
119
+ getPublishStreamPart(topic) {
120
+ const { base, query } = (0, parser_1.parseQueryAndBase)(topic);
121
+ return {
122
+ streamId: this.getStreamId(base),
123
+ ...(0, partitions_1.parsePublishPartitionDefinition)(query)
124
+ };
125
+ }
126
+ getStreamId(topicBase) {
127
+ return (0, protocol_1.toStreamID)((this.streamIdDomain !== undefined) ? `${this.streamIdDomain}/${topicBase}` : topicBase);
128
+ }
129
+ getSubscription(streamPartId) {
130
+ return this.subscriptions.find((s) => {
131
+ return s.streamrClientSubscription.streamPartId === streamPartId;
132
+ });
133
+ }
134
+ }
135
+ exports.Bridge = Bridge;
136
+ //# sourceMappingURL=Bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Bridge.js","sourceRoot":"","sources":["../../../../src/plugins/mqtt/Bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Schema } from 'ajv';
2
+ import { StreamrClient } from '@streamr/sdk';
3
+ import { ApiPluginConfig, Plugin } from '../../Plugin';
4
+ export interface MqttPluginConfig extends ApiPluginConfig {
5
+ port: number;
6
+ streamIdDomain?: string;
7
+ payloadMetadata: boolean;
8
+ }
9
+ export declare class MqttPlugin extends Plugin<MqttPluginConfig> {
10
+ private server?;
11
+ start(streamrClient: StreamrClient): Promise<void>;
12
+ stop(): Promise<void>;
13
+ getConfigSchema(): Schema;
14
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MqttPlugin = void 0;
7
+ const Plugin_1 = require("../../Plugin");
8
+ const PayloadFormat_1 = require("../../helpers/PayloadFormat");
9
+ const Bridge_1 = require("./Bridge");
10
+ const MqttServer_1 = require("./MqttServer");
11
+ const config_schema_json_1 = __importDefault(require("./config.schema.json"));
12
+ class MqttPlugin extends Plugin_1.Plugin {
13
+ server;
14
+ async start(streamrClient) {
15
+ this.server = new MqttServer_1.MqttServer(this.pluginConfig.port, this.getApiAuthentication());
16
+ const bridge = new Bridge_1.Bridge(streamrClient, this.server, (0, PayloadFormat_1.getPayloadFormat)(this.pluginConfig.payloadMetadata), this.pluginConfig.streamIdDomain);
17
+ this.server.setListener(bridge);
18
+ return this.server.start();
19
+ }
20
+ // eslint-disable-next-line class-methods-use-this
21
+ async stop() {
22
+ await this.server.stop();
23
+ }
24
+ // eslint-disable-next-line class-methods-use-this
25
+ getConfigSchema() {
26
+ return config_schema_json_1.default;
27
+ }
28
+ }
29
+ exports.MqttPlugin = MqttPlugin;
30
+ //# sourceMappingURL=MqttPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MqttPlugin.js","sourceRoot":"","sources":["../../../../src/plugins/mqtt/MqttPlugin.ts"],"names":[],"mappings":";;;;;;AAEA,yCAAsD;AACtD,+DAA8D;AAC9D,qCAAiC;AACjC,6CAAyC;AACzC,8EAAuD;AAQvD,MAAa,UAAW,SAAQ,eAAwB;IAE5C,MAAM,CAAa;IAE3B,KAAK,CAAC,KAAK,CAAC,aAA4B;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,uBAAU,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAA;QACjF,MAAM,MAAM,GAAG,IAAI,eAAM,CACrB,aAAa,EACb,IAAI,CAAC,MAAM,EACX,IAAA,gCAAgB,EAAC,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,EACnD,IAAI,CAAC,YAAY,CAAC,cAAc,CACnC,CAAA;QACD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAC/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IAC9B,CAAC;IAED,kDAAkD;IAClD,KAAK,CAAC,IAAI;QACN,MAAM,IAAI,CAAC,MAAO,CAAC,IAAI,EAAE,CAAA;IAC7B,CAAC;IAED,kDAAkD;IACzC,eAAe;QACpB,OAAO,4BAAoB,CAAA;IAC/B,CAAC;CACJ;AAzBD,gCAyBC"}
@@ -0,0 +1,22 @@
1
+ import { ApiAuthentication } from '../../apiAuthentication';
2
+ export interface MqttServerListener {
3
+ onMessageReceived(topic: string, payload: string, clientId: string): void;
4
+ onSubscribed(topics: string, clientId: string): void;
5
+ onUnsubscribed(topics: string, clientId: string): void;
6
+ }
7
+ export declare class MqttServer {
8
+ private static COMMAND_PUBLISH;
9
+ private static QOS_EXACTLY_ONCE;
10
+ private static BAD_USERNAME_OR_PASSWORD;
11
+ private static NOT_AUTHORIZED;
12
+ private readonly port;
13
+ private readonly aedes;
14
+ private server?;
15
+ private listener?;
16
+ constructor(port: number, apiAuthentication?: ApiAuthentication);
17
+ setListener(listener: MqttServerListener): void;
18
+ start(): Promise<void>;
19
+ stop(): Promise<void>;
20
+ publish(topic: string, payload: string): void;
21
+ private static createAuthenicationHandler;
22
+ }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.MqttServer = void 0;
30
+ const net = __importStar(require("net"));
31
+ const util_1 = __importDefault(require("util"));
32
+ const utils_1 = require("@streamr/utils");
33
+ const apiAuthentication_1 = require("../../apiAuthentication");
34
+ const aedes_1 = __importDefault(require("aedes"));
35
+ const logger = new utils_1.Logger(module);
36
+ class MqttServer {
37
+ static COMMAND_PUBLISH = 'publish';
38
+ static QOS_EXACTLY_ONCE = 2;
39
+ static BAD_USERNAME_OR_PASSWORD = 4;
40
+ static NOT_AUTHORIZED = 5;
41
+ port;
42
+ aedes;
43
+ server;
44
+ listener;
45
+ constructor(port, apiAuthentication) {
46
+ this.port = port;
47
+ this.aedes = new aedes_1.default({
48
+ authenticate: MqttServer.createAuthenicationHandler(apiAuthentication)
49
+ });
50
+ this.aedes.on('publish', (packet, client) => {
51
+ if (client !== null) { // is null if the this server sent the message
52
+ this.listener?.onMessageReceived(packet.topic, packet.payload.toString(), client.id);
53
+ }
54
+ });
55
+ this.aedes.on('subscribe', (subscriptions, client) => {
56
+ const topics = subscriptions.map((subscription) => subscription.topic);
57
+ topics.forEach((topic) => this.listener?.onSubscribed(topic, client.id));
58
+ });
59
+ this.aedes.on('unsubscribe', (topics, client) => {
60
+ topics.forEach((topic) => this.listener?.onUnsubscribed(topic, client.id));
61
+ });
62
+ }
63
+ setListener(listener) {
64
+ this.listener = listener;
65
+ }
66
+ async start() {
67
+ this.server = net.createServer(this.aedes.handle);
68
+ await util_1.default.promisify((callback) => this.server.listen(this.port, callback))();
69
+ logger.info(`Started MQTT server on port ${this.port}`);
70
+ }
71
+ async stop() {
72
+ if (!this.aedes.closed) {
73
+ const closeAedes = util_1.default.promisify((callback) => this.aedes.close(callback))();
74
+ const closeServer = util_1.default.promisify((callback) => this.server.close(callback))();
75
+ await Promise.all([closeAedes, closeServer]);
76
+ logger.info('Stopped MQTT server');
77
+ }
78
+ }
79
+ publish(topic, payload) {
80
+ const packet = {
81
+ topic,
82
+ payload,
83
+ cmd: MqttServer.COMMAND_PUBLISH,
84
+ qos: MqttServer.QOS_EXACTLY_ONCE,
85
+ dup: false,
86
+ retain: false
87
+ };
88
+ this.aedes.publish(packet, (error) => {
89
+ if (error) {
90
+ logger.warn('Failed to publish', { error, topic });
91
+ }
92
+ });
93
+ }
94
+ static createAuthenicationHandler(apiAuthentication) {
95
+ return (_client, _username, password, done) => {
96
+ if ((0, apiAuthentication_1.isValidAuthentication)(password?.toString(), apiAuthentication)) {
97
+ done(null, true);
98
+ }
99
+ else {
100
+ const error = Object.assign(new Error(), {
101
+ returnCode: (password !== undefined) ? MqttServer.BAD_USERNAME_OR_PASSWORD : MqttServer.NOT_AUTHORIZED
102
+ });
103
+ done(error, false);
104
+ }
105
+ };
106
+ }
107
+ }
108
+ exports.MqttServer = MqttServer;
109
+ //# sourceMappingURL=MqttServer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MqttServer.js","sourceRoot":"","sources":["../../../../src/plugins/mqtt/MqttServer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ {
2
+ "$id": "config.schema.json",
3
+ "$schema": "http://json-schema.org/draft-07/schema#",
4
+ "type": "object",
5
+ "description": "MQTT plugin configuration",
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "port": {
9
+ "type": "integer",
10
+ "description": "Port to start plugin on",
11
+ "default": 1883
12
+ },
13
+ "streamIdDomain": {
14
+ "type": "string",
15
+ "description": "All topics are mapped to streamIds by prepending the domain to the topic: streamIdDomain + '/' + topic"
16
+ },
17
+ "payloadMetadata": {
18
+ "type": "boolean",
19
+ "description": "The format of payloads: payload is wrapped as { content, metadata } or is a plain content JSON",
20
+ "default": false
21
+ },
22
+ "apiAuthentication": {
23
+ "$ref": "definitions.schema.json#/definitions/apiAuthenticationOverride"
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,20 @@
1
+ import { DhtAddress } from '@streamr/dht';
2
+ import { StreamPartID } from '@streamr/protocol';
3
+ /**
4
+ * A wrapper for "consistent-hash" library that provides us with additional guarantees such as
5
+ *
6
+ * (1) node insertion order doesn't affect result
7
+ *
8
+ * (2) minor variations in resource suffixes are properly assigned around
9
+ *
10
+ * See the corresponding test, ConstHash.test.ts, for details.
11
+ */
12
+ export declare class ConsistentHashRing {
13
+ private readonly nodes;
14
+ private consistentHash?;
15
+ private readonly redundancyFactor;
16
+ constructor(redundancyFactor: number);
17
+ add(nodeId: DhtAddress): void;
18
+ remove(nodeId: DhtAddress): void;
19
+ get(streamPartId: StreamPartID): DhtAddress[];
20
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ConsistentHashRing = void 0;
7
+ const protocol_1 = require("@streamr/protocol");
8
+ const consistent_hash_1 = __importDefault(require("consistent-hash"));
9
+ /**
10
+ * Slight variations at the very end of a string will not result in the keys
11
+ * being sufficiently assigned around. By having the partition number first,
12
+ * we properly randomize the assignments of stream parts of a stream.
13
+ *
14
+ * TODO: use md5 instead?
15
+ */
16
+ function formKey(streamPartId) {
17
+ const [streamId, partition] = protocol_1.StreamPartIDUtils.getStreamIDAndPartition(streamPartId);
18
+ return `${partition}#${streamId}`;
19
+ }
20
+ /**
21
+ * A wrapper for "consistent-hash" library that provides us with additional guarantees such as
22
+ *
23
+ * (1) node insertion order doesn't affect result
24
+ *
25
+ * (2) minor variations in resource suffixes are properly assigned around
26
+ *
27
+ * See the corresponding test, ConstHash.test.ts, for details.
28
+ */
29
+ class ConsistentHashRing {
30
+ nodes = new Array();
31
+ consistentHash;
32
+ redundancyFactor;
33
+ constructor(redundancyFactor) {
34
+ this.redundancyFactor = redundancyFactor;
35
+ }
36
+ add(nodeId) {
37
+ if (!this.nodes.includes(nodeId)) {
38
+ this.nodes.push(nodeId);
39
+ this.consistentHash = undefined;
40
+ }
41
+ }
42
+ remove(nodeId) {
43
+ const idx = this.nodes.indexOf(nodeId);
44
+ if (idx !== -1) {
45
+ this.nodes.splice(idx, 1);
46
+ this.consistentHash = undefined;
47
+ }
48
+ }
49
+ get(streamPartId) {
50
+ if (this.consistentHash === undefined) {
51
+ this.consistentHash = new consistent_hash_1.default({
52
+ distribution: 'uniform'
53
+ });
54
+ this.nodes.sort();
55
+ for (const nodeId of this.nodes) {
56
+ this.consistentHash.add(nodeId);
57
+ }
58
+ }
59
+ const result = this.consistentHash.get(formKey(streamPartId), this.redundancyFactor);
60
+ return result ?? [];
61
+ }
62
+ }
63
+ exports.ConsistentHashRing = ConsistentHashRing;
64
+ //# sourceMappingURL=ConsistentHashRing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConsistentHashRing.js","sourceRoot":"","sources":["../../../../src/plugins/operator/ConsistentHashRing.ts"],"names":[],"mappings":";;;;;;AACA,gDAAmE;AACnE,sEAA4C;AAE5C;;;;;;GAMG;AACH,SAAS,OAAO,CAAC,YAA0B;IACvC,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,4BAAiB,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAA;IACrF,OAAO,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAA;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAa,kBAAkB;IACV,KAAK,GAAG,IAAI,KAAK,EAAc,CAAA;IACxC,cAAc,CAAiB;IACtB,gBAAgB,CAAQ;IAEzC,YAAY,gBAAwB;QAChC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAA;IAC5C,CAAC;IAED,GAAG,CAAC,MAAkB;QAClB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACvB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAA;QACnC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,MAAkB;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACtC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YACzB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAA;QACnC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,YAA0B;QAC1B,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACpC,IAAI,CAAC,cAAc,GAAG,IAAI,yBAAc,CAAC;gBACrC,YAAY,EAAE,SAAS;aAC1B,CAAC,CAAA;YACF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAA;YACjB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC9B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YACnC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAA;QACpF,OAAO,MAAsB,IAAI,EAAE,CAAA;IACvC,CAAC;CACJ;AArCD,gDAqCC"}
@@ -0,0 +1,80 @@
1
+ /// <reference types="node" />
2
+ import { Provider } from '@ethersproject/providers';
3
+ import { Operator } from '@streamr/network-contracts';
4
+ import { StreamID } from '@streamr/protocol';
5
+ import { EthereumAddress, TheGraphClient } from '@streamr/utils';
6
+ import { Overrides } from 'ethers';
7
+ import { NetworkPeerDescriptor } from '@streamr/sdk';
8
+ import { OperatorServiceConfig } from './OperatorPlugin';
9
+ interface EarningsData {
10
+ sponsorshipAddresses: EthereumAddress[];
11
+ sumDataWei: bigint;
12
+ maxAllowedEarningsDataWei: bigint;
13
+ }
14
+ export declare const VOTE_KICK = "0x0000000000000000000000000000000000000000000000000000000000000001";
15
+ export declare const VOTE_NO_KICK = "0x0000000000000000000000000000000000000000000000000000000000000000";
16
+ export declare class ParseError extends Error {
17
+ readonly reasonText: string;
18
+ constructor(reasonText: string);
19
+ }
20
+ export declare function parsePartitionFromReviewRequestMetadata(metadataAsString: string | undefined): number | never;
21
+ export type ReviewRequestListener = (sponsorship: EthereumAddress, operatorContractAddress: EthereumAddress, partition: number, votingPeriodStartTime: number, votingPeriodEndTime: number) => void;
22
+ export interface SponsorshipResult {
23
+ sponsorshipAddress: EthereumAddress;
24
+ streamId: StreamID;
25
+ operatorCount: number;
26
+ }
27
+ export interface Flag {
28
+ id: string;
29
+ flaggingTimestamp: number;
30
+ target: {
31
+ id: string;
32
+ };
33
+ sponsorship: {
34
+ id: string;
35
+ };
36
+ }
37
+ export declare class ContractFacade {
38
+ private readonly operatorContract;
39
+ private readonly theGraphClient;
40
+ private readonly config;
41
+ constructor(operatorContract: Operator, theGraphClient: TheGraphClient, config: OperatorServiceConfig);
42
+ static createInstance(config: OperatorServiceConfig): ContractFacade;
43
+ writeHeartbeat(nodeDescriptor: NetworkPeerDescriptor): Promise<void>;
44
+ getTimestampOfLastHeartbeat(): Promise<number | undefined>;
45
+ getOperatorContractAddress(): EthereumAddress;
46
+ getSponsorshipsOfOperator(operatorAddress: EthereumAddress): Promise<SponsorshipResult[]>;
47
+ getExpiredFlags(sponsorships: EthereumAddress[], maxAgeInMs: number): Promise<Flag[]>;
48
+ getOperatorsInSponsorship(sponsorshipAddress: EthereumAddress): Promise<EthereumAddress[]>;
49
+ flag(sponsorship: EthereumAddress, operator: EthereumAddress, partition: number): Promise<void>;
50
+ getRandomOperator(): Promise<EthereumAddress | undefined>;
51
+ /**
52
+ * Find the sum of earnings in Sponsorships (that the Operator must withdraw before the sum reaches a limit),
53
+ * SUBJECT TO the constraints, set in the OperatorServiceConfig:
54
+ * - only take at most maxSponsorshipsInWithdraw addresses (those with most earnings), or all if undefined
55
+ * - only take sponsorships that have more than minSponsorshipEarningsInWithdraw, or all if undefined
56
+ */
57
+ getEarningsOf(operatorContractAddress: EthereumAddress, minSponsorshipEarningsInWithdraw: number, maxSponsorshipsInWithdraw: number): Promise<EarningsData>;
58
+ getMyEarnings(minSponsorshipEarningsInWithdraw: number, maxSponsorshipsInWithdraw: number): Promise<EarningsData>;
59
+ withdrawMyEarningsFromSponsorships(sponsorshipAddresses: EthereumAddress[]): Promise<void>;
60
+ triggerWithdraw(targetOperatorAddress: EthereumAddress, sponsorshipAddresses: EthereumAddress[]): Promise<void>;
61
+ private getOperatorAddresses;
62
+ pullStakedStreams(requiredBlockNumber: number): AsyncGenerator<{
63
+ sponsorship: {
64
+ id: string;
65
+ stream: {
66
+ id: string;
67
+ };
68
+ };
69
+ }>;
70
+ hasOpenFlag(operatorAddress: EthereumAddress, sponsorshipAddress: EthereumAddress): Promise<boolean>;
71
+ addReviewRequestListener(listener: ReviewRequestListener, abortSignal: AbortSignal): void;
72
+ getStreamId(sponsorshipAddress: string): Promise<StreamID>;
73
+ voteOnFlag(sponsorship: string, targetOperator: string, kick: boolean): Promise<void>;
74
+ closeFlag(sponsorship: string, targetOperator: string): Promise<void>;
75
+ addOperatorContractStakeEventListener(eventName: 'Staked' | 'Unstaked', listener: (sponsorship: string) => unknown): void;
76
+ removeOperatorContractStakeEventListener(eventName: 'Staked' | 'Unstaked', listener: (sponsorship: string) => unknown): void;
77
+ getProvider(): Provider;
78
+ getEthersOverrides(): Overrides;
79
+ }
80
+ export {};