@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.
- package/LICENSE +78 -0
- package/README.md +54 -0
- package/bin/broker.ts +36 -0
- package/bin/config-wizard.js +4 -0
- package/bin/config-wizard.ts +17 -0
- package/bin/delete-expired-data.ts +41 -0
- package/bin/entry-point.ts +27 -0
- package/configs/development-1.env.json +68 -0
- package/configs/development-2.env.json +53 -0
- package/configs/development-3.env.json +53 -0
- package/configs/development-prod-resend.env.json +21 -0
- package/configs/docker-1.env.json +72 -0
- package/configs/docker-2.env.json +58 -0
- package/configs/docker-3.env.json +58 -0
- package/configuration.md +38 -0
- package/dist/bin/broker.d.ts +2 -0
- package/dist/bin/broker.js +42 -0
- package/dist/bin/broker.js.map +1 -0
- package/dist/bin/config-wizard.d.ts +2 -0
- package/dist/bin/config-wizard.js +22 -0
- package/dist/bin/config-wizard.js.map +1 -0
- package/dist/bin/delete-expired-data.d.ts +2 -0
- package/dist/bin/delete-expired-data.js +44 -0
- package/dist/bin/delete-expired-data.js.map +1 -0
- package/dist/bin/entry-point.d.ts +2 -0
- package/dist/bin/entry-point.js +28 -0
- package/dist/bin/entry-point.js.map +1 -0
- package/dist/package.json +78 -0
- package/dist/src/Plugin.d.ts +33 -0
- package/dist/src/Plugin.js +43 -0
- package/dist/src/Plugin.js.map +1 -0
- package/dist/src/apiAuthentication.d.ts +4 -0
- package/dist/src/apiAuthentication.js +16 -0
- package/dist/src/apiAuthentication.js.map +1 -0
- package/dist/src/broker.d.ts +8 -0
- package/dist/src/broker.js +69 -0
- package/dist/src/broker.js.map +1 -0
- package/dist/src/config/ConfigWizard.d.ts +5 -0
- package/dist/src/config/ConfigWizard.js +466 -0
- package/dist/src/config/ConfigWizard.js.map +1 -0
- package/dist/src/config/config.d.ts +26 -0
- package/dist/src/config/config.js +92 -0
- package/dist/src/config/config.js.map +1 -0
- package/dist/src/config/config.schema.json +86 -0
- package/dist/src/config/definitions.schema.json +35 -0
- package/dist/src/config/migration.d.ts +6 -0
- package/dist/src/config/migration.js +210 -0
- package/dist/src/config/migration.js.map +1 -0
- package/dist/src/config/validateConfig.d.ts +4 -0
- package/dist/src/config/validateConfig.js +40 -0
- package/dist/src/config/validateConfig.js.map +1 -0
- package/dist/src/exports.d.ts +3 -0
- package/dist/src/exports.js +6 -0
- package/dist/src/exports.js.map +1 -0
- package/dist/src/helpers/PayloadFormat.d.ts +19 -0
- package/dist/src/helpers/PayloadFormat.js +85 -0
- package/dist/src/helpers/PayloadFormat.js.map +1 -0
- package/dist/src/helpers/applyPluginClientConfigs.d.ts +3 -0
- package/dist/src/helpers/applyPluginClientConfigs.js +29 -0
- package/dist/src/helpers/applyPluginClientConfigs.js.map +1 -0
- package/dist/src/helpers/fetchOrThrow.d.ts +2 -0
- package/dist/src/helpers/fetchOrThrow.js +20 -0
- package/dist/src/helpers/fetchOrThrow.js.map +1 -0
- package/dist/src/helpers/generateMnemonicFromAddress.d.ts +5 -0
- package/dist/src/helpers/generateMnemonicFromAddress.js +16 -0
- package/dist/src/helpers/generateMnemonicFromAddress.js.map +1 -0
- package/dist/src/helpers/multiply.d.ts +1 -0
- package/dist/src/helpers/multiply.js +10 -0
- package/dist/src/helpers/multiply.js.map +1 -0
- package/dist/src/helpers/parser.d.ts +9 -0
- package/dist/src/helpers/parser.js +62 -0
- package/dist/src/helpers/parser.js.map +1 -0
- package/dist/src/helpers/partitions.d.ts +8 -0
- package/dist/src/helpers/partitions.js +32 -0
- package/dist/src/helpers/partitions.js.map +1 -0
- package/dist/src/helpers/weightedSample.d.ts +16 -0
- package/dist/src/helpers/weightedSample.js +35 -0
- package/dist/src/helpers/weightedSample.js.map +1 -0
- package/dist/src/httpServer.d.ts +16 -0
- package/dist/src/httpServer.js +71 -0
- package/dist/src/httpServer.js.map +1 -0
- package/dist/src/pluginRegistry.d.ts +3 -0
- package/dist/src/pluginRegistry.js +35 -0
- package/dist/src/pluginRegistry.js.map +1 -0
- package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.d.ts +12 -0
- package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js +36 -0
- package/dist/src/plugins/consoleMetrics/ConsoleMetricsPlugin.js.map +1 -0
- package/dist/src/plugins/consoleMetrics/config.schema.json +18 -0
- package/dist/src/plugins/http/HttpPlugin.d.ts +8 -0
- package/dist/src/plugins/http/HttpPlugin.js +23 -0
- package/dist/src/plugins/http/HttpPlugin.js.map +1 -0
- package/dist/src/plugins/http/config.schema.json +12 -0
- package/dist/src/plugins/http/publishEndpoint.d.ts +3 -0
- package/dist/src/plugins/http/publishEndpoint.js +72 -0
- package/dist/src/plugins/http/publishEndpoint.js.map +1 -0
- package/dist/src/plugins/info/InfoPlugin.d.ts +9 -0
- package/dist/src/plugins/info/InfoPlugin.js +31 -0
- package/dist/src/plugins/info/InfoPlugin.js.map +1 -0
- package/dist/src/plugins/info/config.schema.json +12 -0
- package/dist/src/plugins/mqtt/Bridge.d.ts +40 -0
- package/dist/src/plugins/mqtt/Bridge.js +136 -0
- package/dist/src/plugins/mqtt/Bridge.js.map +1 -0
- package/dist/src/plugins/mqtt/MqttPlugin.d.ts +14 -0
- package/dist/src/plugins/mqtt/MqttPlugin.js +30 -0
- package/dist/src/plugins/mqtt/MqttPlugin.js.map +1 -0
- package/dist/src/plugins/mqtt/MqttServer.d.ts +22 -0
- package/dist/src/plugins/mqtt/MqttServer.js +109 -0
- package/dist/src/plugins/mqtt/MqttServer.js.map +1 -0
- package/dist/src/plugins/mqtt/config.schema.json +26 -0
- package/dist/src/plugins/operator/ConsistentHashRing.d.ts +20 -0
- package/dist/src/plugins/operator/ConsistentHashRing.js +64 -0
- package/dist/src/plugins/operator/ConsistentHashRing.js.map +1 -0
- package/dist/src/plugins/operator/ContractFacade.d.ts +80 -0
- package/dist/src/plugins/operator/ContractFacade.js +364 -0
- package/dist/src/plugins/operator/ContractFacade.js.map +1 -0
- package/dist/src/plugins/operator/MaintainTopologyHelper.d.ts +23 -0
- package/dist/src/plugins/operator/MaintainTopologyHelper.js +75 -0
- package/dist/src/plugins/operator/MaintainTopologyHelper.js.map +1 -0
- package/dist/src/plugins/operator/MaintainTopologyService.d.ts +11 -0
- package/dist/src/plugins/operator/MaintainTopologyService.js +57 -0
- package/dist/src/plugins/operator/MaintainTopologyService.js.map +1 -0
- package/dist/src/plugins/operator/OperatorFleetState.d.ts +33 -0
- package/dist/src/plugins/operator/OperatorFleetState.js +112 -0
- package/dist/src/plugins/operator/OperatorFleetState.js.map +1 -0
- package/dist/src/plugins/operator/OperatorPlugin.d.ts +50 -0
- package/dist/src/plugins/operator/OperatorPlugin.js +159 -0
- package/dist/src/plugins/operator/OperatorPlugin.js.map +1 -0
- package/dist/src/plugins/operator/StreamPartAssignments.d.ts +28 -0
- package/dist/src/plugins/operator/StreamPartAssignments.js +104 -0
- package/dist/src/plugins/operator/StreamPartAssignments.js.map +1 -0
- package/dist/src/plugins/operator/announceNodeToContract.d.ts +3 -0
- package/dist/src/plugins/operator/announceNodeToContract.js +39 -0
- package/dist/src/plugins/operator/announceNodeToContract.js.map +1 -0
- package/dist/src/plugins/operator/announceNodeToStream.d.ts +3 -0
- package/dist/src/plugins/operator/announceNodeToStream.js +25 -0
- package/dist/src/plugins/operator/announceNodeToStream.js.map +1 -0
- package/dist/src/plugins/operator/checkOperatorValueBreach.d.ts +2 -0
- package/dist/src/plugins/operator/checkOperatorValueBreach.js +21 -0
- package/dist/src/plugins/operator/checkOperatorValueBreach.js.map +1 -0
- package/dist/src/plugins/operator/closeExpiredFlags.d.ts +3 -0
- package/dist/src/plugins/operator/closeExpiredFlags.js +24 -0
- package/dist/src/plugins/operator/closeExpiredFlags.js.map +1 -0
- package/dist/src/plugins/operator/config.schema.json +152 -0
- package/dist/src/plugins/operator/createIsLeaderFn.d.ts +4 -0
- package/dist/src/plugins/operator/createIsLeaderFn.js +14 -0
- package/dist/src/plugins/operator/createIsLeaderFn.js.map +1 -0
- package/dist/src/plugins/operator/fetchRedundancyFactor.d.ts +2 -0
- package/dist/src/plugins/operator/fetchRedundancyFactor.js +43 -0
- package/dist/src/plugins/operator/fetchRedundancyFactor.js.map +1 -0
- package/dist/src/plugins/operator/formCoordinationStreamId.d.ts +3 -0
- package/dist/src/plugins/operator/formCoordinationStreamId.js +9 -0
- package/dist/src/plugins/operator/formCoordinationStreamId.js.map +1 -0
- package/dist/src/plugins/operator/heartbeatUtils.d.ts +67 -0
- package/dist/src/plugins/operator/heartbeatUtils.js +26 -0
- package/dist/src/plugins/operator/heartbeatUtils.js.map +1 -0
- package/dist/src/plugins/operator/inspectOverTime.d.ts +22 -0
- package/dist/src/plugins/operator/inspectOverTime.js +146 -0
- package/dist/src/plugins/operator/inspectOverTime.js.map +1 -0
- package/dist/src/plugins/operator/inspectRandomNode.d.ts +8 -0
- package/dist/src/plugins/operator/inspectRandomNode.js +44 -0
- package/dist/src/plugins/operator/inspectRandomNode.js.map +1 -0
- package/dist/src/plugins/operator/inspectionUtils.d.ts +23 -0
- package/dist/src/plugins/operator/inspectionUtils.js +120 -0
- package/dist/src/plugins/operator/inspectionUtils.js.map +1 -0
- package/dist/src/plugins/operator/maintainOperatorValue.d.ts +2 -0
- package/dist/src/plugins/operator/maintainOperatorValue.js +21 -0
- package/dist/src/plugins/operator/maintainOperatorValue.js.map +1 -0
- package/dist/src/plugins/operator/reviewSuspectNode.d.ts +24 -0
- package/dist/src/plugins/operator/reviewSuspectNode.js +56 -0
- package/dist/src/plugins/operator/reviewSuspectNode.js.map +1 -0
- package/dist/src/plugins/storage/Batch.d.ts +51 -0
- package/dist/src/plugins/storage/Batch.js +121 -0
- package/dist/src/plugins/storage/Batch.js.map +1 -0
- package/dist/src/plugins/storage/BatchManager.d.ts +27 -0
- package/dist/src/plugins/storage/BatchManager.js +117 -0
- package/dist/src/plugins/storage/BatchManager.js.map +1 -0
- package/dist/src/plugins/storage/Bucket.d.ts +23 -0
- package/dist/src/plugins/storage/Bucket.js +90 -0
- package/dist/src/plugins/storage/Bucket.js.map +1 -0
- package/dist/src/plugins/storage/BucketManager.d.ts +56 -0
- package/dist/src/plugins/storage/BucketManager.js +306 -0
- package/dist/src/plugins/storage/BucketManager.js.map +1 -0
- package/dist/src/plugins/storage/DataQueryFormat.d.ts +10 -0
- package/dist/src/plugins/storage/DataQueryFormat.js +51 -0
- package/dist/src/plugins/storage/DataQueryFormat.js.map +1 -0
- package/dist/src/plugins/storage/DeleteExpiredCmd.d.ts +28 -0
- package/dist/src/plugins/storage/DeleteExpiredCmd.js +155 -0
- package/dist/src/plugins/storage/DeleteExpiredCmd.js.map +1 -0
- package/dist/src/plugins/storage/SetMembershipSynchronizer.d.ts +33 -0
- package/dist/src/plugins/storage/SetMembershipSynchronizer.js +102 -0
- package/dist/src/plugins/storage/SetMembershipSynchronizer.js.map +1 -0
- package/dist/src/plugins/storage/Storage.d.ts +47 -0
- package/dist/src/plugins/storage/Storage.js +459 -0
- package/dist/src/plugins/storage/Storage.js.map +1 -0
- package/dist/src/plugins/storage/StorageConfig.d.ts +43 -0
- package/dist/src/plugins/storage/StorageConfig.js +83 -0
- package/dist/src/plugins/storage/StorageConfig.js.map +1 -0
- package/dist/src/plugins/storage/StorageEventListener.d.ts +17 -0
- package/dist/src/plugins/storage/StorageEventListener.js +46 -0
- package/dist/src/plugins/storage/StorageEventListener.js.map +1 -0
- package/dist/src/plugins/storage/StoragePlugin.d.ts +32 -0
- package/dist/src/plugins/storage/StoragePlugin.js +103 -0
- package/dist/src/plugins/storage/StoragePlugin.js.map +1 -0
- package/dist/src/plugins/storage/StoragePoller.d.ts +15 -0
- package/dist/src/plugins/storage/StoragePoller.js +47 -0
- package/dist/src/plugins/storage/StoragePoller.js.map +1 -0
- package/dist/src/plugins/storage/config.schema.json +88 -0
- package/dist/src/plugins/storage/dataMetadataEndpoint.d.ts +3 -0
- package/dist/src/plugins/storage/dataMetadataEndpoint.js +35 -0
- package/dist/src/plugins/storage/dataMetadataEndpoint.js.map +1 -0
- package/dist/src/plugins/storage/dataQueryEndpoint.d.ts +6 -0
- package/dist/src/plugins/storage/dataQueryEndpoint.js +181 -0
- package/dist/src/plugins/storage/dataQueryEndpoint.js.map +1 -0
- package/dist/src/plugins/storage/storageConfigEndpoint.d.ts +3 -0
- package/dist/src/plugins/storage/storageConfigEndpoint.js +31 -0
- package/dist/src/plugins/storage/storageConfigEndpoint.js.map +1 -0
- package/dist/src/plugins/subscriber/SubscriberPlugin.d.ts +16 -0
- package/dist/src/plugins/subscriber/SubscriberPlugin.js +22 -0
- package/dist/src/plugins/subscriber/SubscriberPlugin.js.map +1 -0
- package/dist/src/plugins/subscriber/config.schema.json +31 -0
- package/dist/src/plugins/websocket/Connection.d.ts +9 -0
- package/dist/src/plugins/websocket/Connection.js +45 -0
- package/dist/src/plugins/websocket/Connection.js.map +1 -0
- package/dist/src/plugins/websocket/PublishConnection.d.ts +12 -0
- package/dist/src/plugins/websocket/PublishConnection.js +46 -0
- package/dist/src/plugins/websocket/PublishConnection.js.map +1 -0
- package/dist/src/plugins/websocket/SubscribeConnection.d.ts +13 -0
- package/dist/src/plugins/websocket/SubscribeConnection.js +50 -0
- package/dist/src/plugins/websocket/SubscribeConnection.js.map +1 -0
- package/dist/src/plugins/websocket/WebsocketPlugin.d.ts +19 -0
- package/dist/src/plugins/websocket/WebsocketPlugin.js +26 -0
- package/dist/src/plugins/websocket/WebsocketPlugin.js.map +1 -0
- package/dist/src/plugins/websocket/WebsocketServer.d.ts +16 -0
- package/dist/src/plugins/websocket/WebsocketServer.js +132 -0
- package/dist/src/plugins/websocket/WebsocketServer.js.map +1 -0
- package/dist/src/plugins/websocket/config.schema.json +51 -0
- package/package.json +78 -0
- 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 {};
|