├── Webpack
├── dist
│ └── .gitkeep
├── .babelrc
├── index.html
├── README.md
├── webpack.config.js
├── package.json
└── src
│ └── index.js
├── .gitignore
├── LightNodeJs
├── src
│ ├── config.js
│ ├── utils.js
│ ├── getStream.js
│ ├── getOrCreateStream.js
│ ├── stream
│ │ ├── delete.js
│ │ ├── update.js
│ │ ├── permissions
│ │ │ ├── getPermissions.js
│ │ │ ├── grantPermissions.js
│ │ │ ├── hasPermission.js
│ │ │ └── revokePermissions.js
│ │ ├── getStorageNodes.js
│ │ ├── removeFromStorageNode.js
│ │ ├── addToStorageNode.js
│ │ └── publish.js
│ ├── createStream.js
│ ├── getSubscriptions.js
│ ├── subscribe.js
│ ├── unsubscribe.js
│ ├── searchStream.js
│ ├── publish.js
│ ├── unsubscribeAll.js
│ ├── setPermissions.js
│ ├── anon.js
│ └── resend.js
├── README.md
├── package.json
└── test
│ ├── Stream.test.js
│ └── Client.test.js
├── RaspberryPi
├── package.json
├── README.md
└── index.js
├── Dockerfile
├── Tutorials
└── mqtt
│ ├── package.json
│ ├── scripts
│ ├── 02-MqttPublisher.js
│ ├── 03-MqttSubscriber.js
│ └── 01-CreateStreamAndAssignPermissions.js
│ └── README.md
├── BrokerApiNode
├── src
│ ├── config.json
│ ├── util.js
│ ├── api-key-auth
│ │ ├── config.json
│ │ ├── ws-subscribe.js
│ │ ├── mqtt-subscribe.js
│ │ ├── ws-publish.js
│ │ ├── http-publish.js
│ │ └── mqtt-publish.js
│ ├── ws-subscribe.js
│ ├── mqtt-subscribe.js
│ ├── ws-publish.js
│ ├── mqtt-publish.js
│ └── http-publish.js
├── test
│ ├── http.test.js
│ ├── api-key-auth
│ │ ├── http.apiKey.test.js
│ │ ├── mqtt.apiKey.test.js
│ │ └── ws.apiKey.test.js
│ ├── ws.test.js
│ ├── mqtt.test.js
│ └── util.js
├── package.json
└── README.md
├── Browser
├── package.json
├── README.md
└── www
│ ├── web-example-publish.html
│ ├── web-example-metamask.html
│ └── web-example-subscribe.html
├── .github
├── workflows
│ ├── markdown-link-check.yaml
│ └── close-stale-issue-and-pr.yaml
└── dependabot.yaml
├── BrokerApiPython
├── ws-publish.py
├── mqtt-subscribe.py
├── mqtt-publish.py
└── requirements.txt
└── README.md
/Webpack/dist/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | venv
3 | .env
4 |
--------------------------------------------------------------------------------
/LightNodeJs/src/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | PrivateKey: "",
3 | };
4 |
--------------------------------------------------------------------------------
/Webpack/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env"]],
3 | "plugins": ["add-module-exports", ["@babel/transform-runtime"]]
4 | }
5 |
--------------------------------------------------------------------------------
/RaspberryPi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "RaspberryPiClient",
3 | "scripts": {
4 | "start": "node index.js"
5 | },
6 | "dependencies": {
7 | "streamr-client": "latest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Webpack/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Subscribe
6 | Publish
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM debian:buster AS builder
2 | #RUN echo build app
3 |
4 | FROM debian:buster-slim
5 | RUN apt-get update && apt-get --assume-yes --no-install-recommends install \
6 | netcat
7 | #COPY --from=builder /build/file /bin/target
8 | HEALTHCHECK --interval=10s --timeout=10s --start-period=10s --retries=60 CMD nc -v -z localhost 80
9 |
10 |
--------------------------------------------------------------------------------
/Tutorials/mqtt/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "streamr-mqtt-tutorial",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "async-mqtt": "^2.6.2",
13 | "streamr-client": "^6.0.4"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.streamr.network/config-v1.schema.json",
3 | "client": {
4 | "auth": {
5 | "privateKey": "0x511fa6b9c1fdea50e52412e8142ed5e3918c4c0223d55a46b3870a5a2c6c2e51"
6 | }
7 | },
8 | "plugins": {
9 | "metrics": {},
10 | "websocket": {
11 | "port": 9091
12 | },
13 | "mqtt": {
14 | "port": 9092
15 | },
16 | "publishHttp": {}
17 | },
18 | "httpServer": {
19 | "port": 9093
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/util.js:
--------------------------------------------------------------------------------
1 | const {
2 | uniqueNamesGenerator,
3 | adjectives,
4 | colors,
5 | animals,
6 | } = require("unique-names-generator");
7 |
8 | module.exports = {
9 | isRunFlagPresent: (args) => {
10 | args = args.slice(2);
11 | return args.length > 0 && args[0] === "--run";
12 | },
13 |
14 | getRandomPublisherName: () => {
15 | return uniqueNamesGenerator({
16 | dictionaries: [adjectives, colors, animals],
17 | separator: "-",
18 | length: 3,
19 | });
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/Browser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "streamr-browser-examples",
3 | "version": "1.0.0",
4 | "description": "This example demostrates how to use the Streamr Client with plain HTML. These examples use the web version of the Streamr JS client, pulled from the external [Unpkg service](https://unpkg.com/streamr-client).",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "live-server ./www/"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "live-server": "^1.2.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/.github/workflows/markdown-link-check.yaml:
--------------------------------------------------------------------------------
1 | name: Markdown CI
2 |
3 | # https://github.com/gaurav-nelson/github-action-markdown-link-check
4 |
5 | on:
6 | schedule:
7 | - cron: "0 5 * * 1"
8 |
9 | jobs:
10 | check-links:
11 | name: Check Markdown links
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2.3.4
15 | - uses: gaurav-nelson/github-action-markdown-link-check@1.0.12
16 | with:
17 | use-quiet-mode: 'yes'
18 | use-verbose-mode: 'yes'
19 | max-depth: 1
20 |
--------------------------------------------------------------------------------
/LightNodeJs/src/utils.js:
--------------------------------------------------------------------------------
1 | const { Wallet } = require("ethers");
2 | const { PrivateKey } = require("./config.js");
3 | module.exports = {
4 | isValidPrivateKey: (privateKey) => {
5 | try {
6 | const w = new Wallet(privateKey);
7 | } catch (e) {
8 | console.error(
9 | "You need to provide a Private Key under /src/config.js before you can execute this example."
10 | );
11 | process.exit(1);
12 | }
13 | },
14 |
15 | isRunFlagPresent: (args) => {
16 | args = args.slice(2);
17 | return args.length > 0 && args[0] === "--run";
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/api-key-auth/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://schema.streamr.network/config-v1.schema.json",
3 | "client": {
4 | "auth": {
5 | "privateKey": "0x511fa6b9c1fdea50e52412e8142ed5e3918c4c0223d55a46b3870a5a2c6c2e51"
6 | }
7 | },
8 | "plugins": {
9 | "metrics": {},
10 | "websocket": {
11 | "port": 7071
12 | },
13 | "mqtt": {
14 | "port": 7072
15 | },
16 | "publishHttp": {}
17 | },
18 | "apiAuthentication": {
19 | "keys": ["Y2U1MjU2YzhkNmQxNGNjOGIxZjRlY2ViYWVmNGM5Nzc"]
20 | },
21 | "httpServer": {
22 | "port": 7073
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Webpack/README.md:
--------------------------------------------------------------------------------
1 | # Webpack
2 |
3 | This example demostrates how to use the Streamr Client with Webpack.
4 |
5 | ## Setting Up
6 |
7 | Install dependencies using npm:
8 |
9 | `npm install`
10 |
11 | ### Etherum Private Key
12 |
13 | This script requires an ethereum private key. Replace the  with your private key.
14 |
15 | ## Running
16 |
17 | Use `npm run dev` to compile JavaScript code. Run `open index.html` to view the page. You can also use live-server to enable automatic reloading of the page.
18 |
--------------------------------------------------------------------------------
/Tutorials/mqtt/scripts/02-MqttPublisher.js:
--------------------------------------------------------------------------------
1 | const mqtt = require('async-mqtt')
2 |
3 | const StreamId = '0x123/your/stream/id'
4 | const ApiKey = 'YOUR_API_KEY'
5 |
6 | const main = async () => {
7 | const client = await mqtt.connectAsync('mqtt://localhost:1883',
8 | {
9 | username: '',
10 | password: ApiKey,
11 | })
12 | console.log('connected')
13 |
14 | setInterval(async () => {
15 | const msg = {
16 | "greeting": "Hello world!",
17 | }
18 | await client.publish(StreamId, JSON.stringify(msg))
19 | console.log('Publishing: ', msg)
20 | }, 1000)
21 | }
22 |
23 | main()
--------------------------------------------------------------------------------
/LightNodeJs/src/getStream.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 |
13 | const streamId = `${await client.getAddress()}/light-node-js-example`;
14 | const stream = await client.getStream(streamId);
15 | console.log(`Stream ${stream.id} fetched`);
16 | await client.destroy();
17 | return stream.id;
18 | };
19 |
20 | if (utils.isRunFlagPresent(process.argv)) {
21 | main();
22 | }
23 |
24 | module.exports = main;
25 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 |
2 | # https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: github-actions
7 | directory: /
8 | schedule:
9 | interval: daily
10 | time: '08:00'
11 | timezone: Europe/Helsinki
12 | open-pull-requests-limit: 2
13 | labels:
14 | - actions
15 | - dependencies
16 | # reviewers:
17 | # - TODO
18 |
19 | # - package-ecosystem: npm
20 | # directory: /
21 | # schedule:
22 | # interval: daily
23 | # time: '08:00'
24 | # timezone: Europe/Helsinki
25 | # open-pull-requests-limit: 2
26 | # labels:
27 | # - npm
28 | # - dependencies
29 | # reviewers:
30 | # - TODO
31 |
--------------------------------------------------------------------------------
/Tutorials/mqtt/scripts/03-MqttSubscriber.js:
--------------------------------------------------------------------------------
1 | const mqtt = require('mqtt')
2 |
3 | const StreamId = '0x123/your/stream/id'
4 | const ApiKey = 'YOUR_API_KEY'
5 |
6 | const main = async () => {
7 | const client = mqtt.connect('mqtt://localhost:1883',
8 | {
9 | username: '',
10 | password: ApiKey,
11 | })
12 |
13 | client.subscribe(StreamId, (err) => {
14 | if (err) {
15 | console.log('💥 error subscribing: ', err)
16 | }
17 | })
18 |
19 | client.on('connect', () => {
20 | console.log('connected')
21 | client.on('message', (streamId, rawData) => {
22 | const data = JSON.parse(rawData.toString())
23 | console.log('🎉 received: ', streamId, data)
24 | })
25 | })
26 | }
27 |
28 | main()
--------------------------------------------------------------------------------
/LightNodeJs/src/getOrCreateStream.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 |
13 | // Get or create the default stream
14 | const stream = await client.getOrCreateStream({
15 | id: `/light-node-js-example/${Date.now()}`,
16 | });
17 |
18 | console.log("Stream fetched/created: ", stream.id);
19 | await client.destroy();
20 | return stream.id;
21 | };
22 |
23 | if (utils.isRunFlagPresent(process.argv)) {
24 | main();
25 | }
26 |
27 | module.exports = main;
28 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/delete.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient } = require("streamr-client");
2 | const utils = require("../utils.js");
3 | const { PrivateKey } = require("../config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 | // Create the client using the validated private key
8 | const client = new StreamrClient({
9 | auth: {
10 | privateKey: PrivateKey,
11 | },
12 | });
13 |
14 | // Create the default stream
15 | const stream = await client.getOrCreateStream({
16 | id: `/light-node-js-example/delete`,
17 | });
18 |
19 | console.log("Stream created", stream.id);
20 | await stream.delete();
21 |
22 | console.log("Stream deleted");
23 | };
24 |
25 | if (utils.isRunFlagPresent(process.argv)) {
26 | main();
27 | }
28 |
29 | module.exports = main;
30 |
--------------------------------------------------------------------------------
/LightNodeJs/src/createStream.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient } = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 |
13 | // Create the default stream
14 | const stream = await client.createStream({
15 | id: `/light-node-js-example/${Date.now()}`,
16 | // partitions: 5
17 | });
18 |
19 | console.log("Stream created:", stream.id);
20 | await client.destroy();
21 | return stream.id;
22 | };
23 |
24 | if (utils.isRunFlagPresent(process.argv)) {
25 | main();
26 | }
27 |
28 | module.exports = main;
29 |
--------------------------------------------------------------------------------
/BrokerApiPython/ws-publish.py:
--------------------------------------------------------------------------------
1 | import websocket
2 | import _thread
3 | import time
4 |
5 | def on_message(ws, message):
6 | print(message)
7 |
8 | def on_error(ws, error):
9 | print(error)
10 |
11 | def on_close(ws, close_status_code, close_msg):
12 | print("### closed ###")
13 |
14 | def on_open(ws):
15 | def run(*args):
16 | for i in range(3):
17 | time.sleep(1)
18 | ws.send("Hello %d" % i)
19 | time.sleep(1)
20 | ws.close()
21 | print("thread terminating...")
22 | _thread.start_new_thread(run, ())
23 |
24 | if __name__ == "__main__":
25 | websocket.enableTrace(True)
26 | ws = websocket.WebSocketApp("ws://echo.websocket.org/",
27 | on_open=on_open,
28 | on_message=on_message,
29 | on_error=on_error,
30 | on_close=on_close)
31 |
32 | ws.run_forever()
--------------------------------------------------------------------------------
/Webpack/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable prefer-template */
2 | /* eslint-disable prefer-destructuring */
3 |
4 | const path = require('path')
5 |
6 | module.exports = {
7 | entry: path.join(__dirname, 'src', 'index.js'),
8 | target: 'web',
9 | devtool: 'source-map',
10 | output: {
11 | libraryTarget: 'umd2',
12 | path: path.join(__dirname, 'dist'),
13 | filename: 'webpack-example.js',
14 | },
15 | module: {
16 | rules: [
17 | {
18 | test: /(\.jsx|\.js)$/,
19 | loader: 'babel-loader',
20 | exclude: /(node_modules|bower_components)/
21 | },
22 | ],
23 | },
24 | resolve: {
25 | modules: [path.resolve('./node_modules'), path.resolve('./src')],
26 | extensions: ['.json', '.js'],
27 | },
28 | plugins: [],
29 | }
30 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/ws-subscribe.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require("ws").WebSocket;
2 | const util = require("./util");
3 |
4 | const main = async (port = 9091) => {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | const streamId = encodeURIComponent(
8 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example"
9 | );
10 | const ws = new WebSocket(
11 | `ws://localhost:${port}/streams/${streamId}/subscribe`
12 | );
13 |
14 | ws.on("message", (json) => {
15 | const data = JSON.parse(json);
16 | console.log("Received data: ", data);
17 | });
18 | console.log("websocket listener connected");
19 | resolve();
20 | } catch (e) {
21 | reject(e);
22 | }
23 | });
24 | };
25 |
26 | if (util.isRunFlagPresent(process.argv)) {
27 | main();
28 | }
29 |
30 | module.exports = main;
31 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/update.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("../utils.js");
3 | const { PrivateKey } = require("../config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 |
8 | // Create the client using the validated private key
9 | const client = new StreamrClient({
10 | auth: {
11 | privateKey: PrivateKey,
12 | },
13 | });
14 |
15 | // Create the default stream
16 | const stream = await client.createStream({
17 | id: `/light-node-js-example/${Date.now()}`,
18 | });
19 | console.log("created stream", stream.id);
20 | stream.description = `Description ${Date.now()}`;
21 | await stream.update();
22 | console.log("Stream updated:", stream.id, stream.description);
23 | };
24 |
25 | if (utils.isRunFlagPresent(process.argv)) {
26 | main();
27 | }
28 |
29 | module.exports = main;
30 |
--------------------------------------------------------------------------------
/RaspberryPi/README.md:
--------------------------------------------------------------------------------
1 | # Raspberry Pi CPU Usage Stream
2 | This simple node script first reads through the RPi system to get the CPU usage.
3 |
4 | Video Tutorial: https://youtu.be/WHmCSKq2CdI
5 |
6 | ## Setting Up
7 |
8 | ### Etherum Private Key
9 |
10 | Install dependencies using npm or yarn:
11 |
12 | `npm install` or `yarn install`
13 |
14 | This script requires an ethereum private key. You should create a `.env` file in the root directory and add this line:
15 |
16 | `ETHEREUM_PrivateKey=`
17 |
18 | Paste your private key after the equals sign.
19 |
20 | ### Stream ID
21 |
22 | You will also need a Stream ID which you can get by creating a new Stream on Streamr Core and replace [this line](https://github.com/streamr-dev/examples/blob/89c374d3b182044178f19dd0875da98aa02a088a/RaspberryPiClient/index.js#L43).
23 |
24 | ## Running
25 |
26 | Use `npm run start` or `yarn start` to run node script.
27 |
--------------------------------------------------------------------------------
/LightNodeJs/src/getSubscriptions.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 |
13 | // Create the default stream
14 | const stream = await client.getOrCreateStream({
15 | id: `/light-node-js-example`,
16 | });
17 | // subscribe to the default stream
18 | await client.subscribe({ stream: stream.id });
19 | const subs = await client.getSubscriptions();
20 | console.log("subscriptions", subs);
21 | await client.destroy();
22 | return subs;
23 | };
24 |
25 | if (utils.isRunFlagPresent(process.argv)) {
26 | main();
27 | }
28 |
29 | module.exports = main;
30 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/permissions/getPermissions.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient } = require("streamr-client");
2 | const utils = require("../../utils.js");
3 | const { PrivateKey } = require("../../config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 | // Create the client using the validated private key
8 | const client = new StreamrClient({
9 | auth: {
10 | privateKey: PrivateKey,
11 | },
12 | });
13 |
14 | const stream = await client.getOrCreateStream({
15 | id: `/light-node-js-example/permissions`,
16 | });
17 |
18 | console.log(`Stream ${stream.id} created`);
19 |
20 | const permissions = await stream.getPermissions();
21 |
22 | console.log("Permissions", permissions);
23 | await client.destroy();
24 | return { permissions, streamId: stream.id };
25 | };
26 |
27 | if (utils.isRunFlagPresent(process.argv)) {
28 | main();
29 | }
30 |
31 | module.exports = main;
32 |
--------------------------------------------------------------------------------
/LightNodeJs/src/subscribe.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 | console.log("client created");
13 |
14 | // Create the default stream
15 | const stream = await client.getOrCreateStream({
16 | id: `/light-node-js-example`,
17 | });
18 |
19 | const subscription = await client.subscribe(
20 | { stream: stream.id },
21 | (message) => {
22 | console.log(JSON.stringify(message));
23 | }
24 | );
25 | console.log("subscription created");
26 | return { client, subscription };
27 | };
28 |
29 | if (utils.isRunFlagPresent(process.argv)) {
30 | main();
31 | }
32 |
33 | module.exports = main;
34 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/mqtt-subscribe.js:
--------------------------------------------------------------------------------
1 | const mqtt = require("mqtt");
2 | const util = require("./util");
3 |
4 | const main = async (port = 9092) => {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | const streamId =
8 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example";
9 | const client = mqtt.connect(`mqtt://localhost:${port}`);
10 |
11 | client.on("connect", () => {
12 | console.log("mqtt listener connected");
13 | client.subscribe(streamId, (err) => {
14 | client.on("message", (streamId, rawData) => {
15 | const json = rawData.toString();
16 | const data = JSON.parse(json);
17 | console.log("Received data: ", data);
18 | });
19 | resolve();
20 | });
21 | });
22 | } catch (e) {
23 | reject(e);
24 | }
25 | });
26 | };
27 |
28 | if (util.isRunFlagPresent(process.argv)) {
29 | main();
30 | }
31 |
32 | module.exports = main;
33 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/http.test.js:
--------------------------------------------------------------------------------
1 | const HttpPublish = require("../src/http-publish");
2 | let BrokerConfig = require("../src/config.json");
3 | const { expectConsoleLogs, startBroker, assignPluginPorts } = require("./util");
4 |
5 | BrokerConfig = assignPluginPorts(BrokerConfig, {
6 | http: 3021,
7 | websocket: 3022,
8 | mqtt: 3023,
9 | });
10 |
11 | describe("HTTP", () => {
12 | let broker;
13 | beforeAll(async () => {
14 | broker = await startBroker(BrokerConfig);
15 | }, 5 * 1000);
16 |
17 | afterAll(async () => {
18 | await broker.stop();
19 | });
20 |
21 | beforeEach(() => {
22 | console.log = jest.fn();
23 | });
24 |
25 | it("should exercise the `publish` example", async () => {
26 | const { interval, httpResponse } = await HttpPublish(
27 | BrokerConfig.httpServer.port
28 | );
29 | expectConsoleLogs(["Sent successfully: "]);
30 | expect(httpResponse.statusCode).toBe(200);
31 | clearInterval(interval);
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/LightNodeJs/src/unsubscribe.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 |
13 | // Create the default stream
14 | const stream = await client.getOrCreateStream({
15 | id: `/light-node-js-example`,
16 | });
17 | console.log("Stream fetched:", stream.id);
18 | const sub = await client.subscribe({ stream: stream.id });
19 | console.log(`Subscribed to stream ${stream.id}`);
20 | await client.unsubscribe({ stream: stream.id });
21 | console.log(`Unsubscribed from stream ${stream.id}`);
22 | await client.destroy();
23 | return stream.id;
24 | };
25 |
26 | if (utils.isRunFlagPresent(process.argv)) {
27 | main();
28 | }
29 |
30 | module.exports = main;
31 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/api-key-auth/ws-subscribe.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require("ws").WebSocket;
2 | const BrokerConfig = require("./config.json");
3 | const util = require("../util");
4 |
5 | const API_KEY = BrokerConfig.apiAuthentication.keys[0];
6 |
7 | const main = async (PORT = 7071) => {
8 | return new Promise((resolve, reject) => {
9 | try {
10 | const streamId = encodeURIComponent(
11 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example"
12 | );
13 | const ws = new WebSocket(
14 | `ws://localhost:${PORT}/streams/${streamId}/subscribe?apiKey=${API_KEY}`
15 | );
16 |
17 | ws.on("message", (json) => {
18 | const data = JSON.parse(json);
19 | console.log("Received data: ", data);
20 | });
21 | console.log("websocket listener connected");
22 |
23 | resolve();
24 | } catch (e) {
25 | reject(e);
26 | }
27 | });
28 | };
29 |
30 | if (util.isRunFlagPresent(process.argv)) {
31 | main();
32 | }
33 |
34 | module.exports = main;
35 |
--------------------------------------------------------------------------------
/LightNodeJs/src/searchStream.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient, StreamPermission } = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | utils.isValidPrivateKey(PrivateKey);
6 | // Create the client using the validated private key
7 | const client = new StreamrClient({
8 | auth: {
9 | privateKey: PrivateKey,
10 | },
11 | });
12 |
13 | const streams = client.searchStreams("light-node-js-example", {
14 | user: await client.getAddress(),
15 | //allOf?: StreamPermission[];
16 | anyOf: [StreamPermission.SUBSCRIBE],
17 | allowPublic: true,
18 | });
19 |
20 | const foundStreams = [];
21 |
22 | for await (const stream of streams) {
23 | foundStreams.push(stream.id);
24 | }
25 |
26 | console.log("streams found:", foundStreams.length, foundStreams);
27 |
28 | return streams;
29 | };
30 |
31 | if (utils.isRunFlagPresent(process.argv)) {
32 | main();
33 | }
34 |
35 | module.exports = main;
36 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/api-key-auth/http.apiKey.test.js:
--------------------------------------------------------------------------------
1 | const HttpApiPublish = require("../../src/api-key-auth/http-publish");
2 | let BrokerConfig = require("../../src/api-key-auth/config.json");
3 | const {
4 | expectConsoleLogs,
5 | startBroker,
6 | assignPluginPorts,
7 | } = require("../util");
8 |
9 | BrokerConfig = assignPluginPorts(BrokerConfig, {
10 | http: 6021,
11 | websocket: 6022,
12 | mqtt: 6023,
13 | });
14 |
15 | describe("HTTP:Api-Key", () => {
16 | let broker;
17 |
18 | beforeAll(async () => {
19 | broker = await startBroker(BrokerConfig);
20 | }, 5 * 1000);
21 |
22 | afterAll(async () => {
23 | await broker.stop();
24 | });
25 |
26 | beforeEach(() => {
27 | console.log = jest.fn();
28 | });
29 |
30 | it("should exercise the `publish` example", async () => {
31 | const { interval, httpResponse } = await HttpApiPublish(
32 | BrokerConfig.httpServer.port
33 | );
34 | expectConsoleLogs(["Sent successfully: "]);
35 | expect(httpResponse.statusCode).toBe(200);
36 | clearInterval(interval);
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/.github/workflows/close-stale-issue-and-pr.yaml:
--------------------------------------------------------------------------------
1 | name: Close stale issues and PRs CI
2 |
3 | on:
4 | schedule:
5 | - cron: "0 0 * * *"
6 |
7 | # https://github.com/marketplace/actions/close-stale-issues
8 |
9 | jobs:
10 | stale:
11 | name: Close stale issues and PRs
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/stale@v3.0.19
15 | with:
16 | repo-token: ${{ secrets.GITHUB_TOKEN }}
17 | days-before-stale: 60
18 | days-before-close: 7
19 | stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove no-issue-activity label or comment or this will be closed in 7 days'
20 | close-issue-message: 'This issue is closed due to inactivity.'
21 | stale-issue-label: 'no-issue-activity'
22 | stale-pr-message: 'This pull request is stale because it has been open 60 days with no activity. Remove no-pr-activity label or comment or this will be closed in 7 days'
23 | close-pr-message: 'This pull request is closed due to inactivity.'
24 | stale-pr-label: 'no-pr-activity'
25 |
26 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/getStorageNodes.js:
--------------------------------------------------------------------------------
1 | const { STREAMR_STORAGE_NODE_GERMANY, StreamrClient } =
2 | require("streamr-client").StreamrClient;
3 | const utils = require("../utils.js");
4 | const { PrivateKey } = require("../config.js");
5 |
6 | const main = async () => {
7 | utils.isValidPrivateKey(PrivateKey);
8 | // Create the client using the validated private key
9 | const client = new StreamrClient({
10 | auth: {
11 | privateKey: PrivateKey,
12 | },
13 | });
14 |
15 | // Create the default stream
16 | const stream = await client.getOrCreateStream({
17 | id: `/light-node-js-example/storage-node`,
18 | });
19 |
20 | console.log("fetched/created stream", stream.id);
21 | if ((await stream.getStorageNodes().length) === 0) {
22 | await stream.addToStorageNode(STREAMR_STORAGE_NODE_GERMANY);
23 | }
24 |
25 | const storageNodes = await stream.getStorageNodes();
26 | console.log("Storage nodes", storageNodes);
27 | await client.destroy();
28 | return stream.id;
29 | };
30 |
31 | if (utils.isRunFlagPresent(process.argv)) {
32 | main();
33 | }
34 |
35 | module.exports = main;
36 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/removeFromStorageNode.js:
--------------------------------------------------------------------------------
1 | const { STREAMR_STORAGE_NODE_GERMANY, StreamrClient } =
2 | require("streamr-client").StreamrClient;
3 | const utils = require("../utils.js");
4 | const { PrivateKey } = require("../config.js");
5 |
6 | const main = async () => {
7 | utils.isValidPrivateKey(PrivateKey);
8 | // Create the client using the validated private key
9 | const client = new StreamrClient({
10 | auth: {
11 | privateKey: PrivateKey,
12 | },
13 | });
14 |
15 | // Create the default stream
16 | const stream = await client.getOrCreateStream({
17 | id: `/light-node-js-example/storage-node`,
18 | });
19 |
20 | console.log("fetched/created stream", stream.id);
21 | if ((await stream.getStorageNodes().length) === 0) {
22 | await stream.addToStorageNode(STREAMR_STORAGE_NODE_GERMANY);
23 | }
24 |
25 | await stream.removeFromStorageNode(STREAMR_STORAGE_NODE_GERMANY);
26 | console.log("Stream removed from storage node");
27 | await client.destroy();
28 | return stream.id;
29 | };
30 |
31 | if (utils.isRunFlagPresent(process.argv)) {
32 | main();
33 | }
34 |
35 | module.exports = main;
36 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/addToStorageNode.js:
--------------------------------------------------------------------------------
1 | const {
2 | STREAMR_STORAGE_NODE_GERMANY,
3 | StreamrClient,
4 | } = require("streamr-client");
5 | const utils = require("../utils.js");
6 | const { PrivateKey } = require("../config.js");
7 |
8 | const main = async () => {
9 | utils.isValidPrivateKey(PrivateKey);
10 | // Create the client using the validated private key
11 | const client = new StreamrClient({
12 | auth: {
13 | privateKey: PrivateKey,
14 | },
15 | });
16 |
17 | // Create the default stream
18 | const stream = await client.getOrCreateStream({
19 | id: `/light-node-js-example/storage-node`,
20 | });
21 | console.log("fetched/created stream", stream.id);
22 | const storageNodes = await stream.getStorageNodes();
23 | if (storageNodes.length === 0) {
24 | await stream.addToStorageNode(STREAMR_STORAGE_NODE_GERMANY);
25 | console.log("Stream added to storage node");
26 | } else {
27 | console.log("stream was already in storage node");
28 | }
29 |
30 | await client.destroy();
31 | return stream.id;
32 | };
33 |
34 | if (utils.isRunFlagPresent(process.argv)) {
35 | main();
36 | }
37 |
38 | module.exports = main;
39 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/ws.test.js:
--------------------------------------------------------------------------------
1 | const WsPublish = require("../src/ws-publish");
2 | const WsSubscribe = require("../src/ws-subscribe");
3 |
4 | let BrokerConfig = require("../src/config.json");
5 | const { expectConsoleLogs, startBroker, assignPluginPorts } = require("./util");
6 |
7 | describe("WS", () => {
8 | let broker;
9 |
10 | BrokerConfig = assignPluginPorts(BrokerConfig, {
11 | http: 5021,
12 | websocket: 5022,
13 | mqtt: 5023,
14 | });
15 |
16 | beforeAll(async () => {
17 | broker = await startBroker(BrokerConfig);
18 | }, 5 * 1000);
19 |
20 | afterAll(async () => {
21 | await broker.stop();
22 | });
23 |
24 | beforeEach(() => {
25 | console.log = jest.fn();
26 | });
27 |
28 | it("should exercise the `subscribe` example", async () => {
29 | await WsSubscribe(BrokerConfig.plugins.websocket.port);
30 | expectConsoleLogs(["websocket listener connected"]);
31 | });
32 |
33 | it("should exercise the `publish` example", async () => {
34 | const { interval } = await WsPublish(BrokerConfig.plugins.websocket.port);
35 | expectConsoleLogs(["Sent successfully: "]);
36 | clearInterval(interval);
37 | });
38 | });
39 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/api-key-auth/mqtt-subscribe.js:
--------------------------------------------------------------------------------
1 | const mqtt = require("mqtt");
2 | const BrokerConfig = require("./config.json");
3 | const util = require("../util");
4 |
5 | const API_KEY = BrokerConfig.apiAuthentication.keys[0];
6 |
7 | const main = async (PORT = 7072) => {
8 | return new Promise((resolve, reject) => {
9 | try {
10 | const streamId =
11 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example";
12 | const client = mqtt.connect(`mqtt://localhost:${PORT}`, {
13 | username: "",
14 | password: API_KEY,
15 | });
16 |
17 | client.on("connect", () => {
18 | client.subscribe(streamId, (err) => {
19 | console.log("mqtt subscribe connected");
20 | client.on("message", (streamId, rawData) => {
21 | const json = rawData.toString();
22 | const data = JSON.parse(json);
23 | console.log("Received data: ", data);
24 | });
25 | resolve();
26 | });
27 | });
28 | } catch (e) {
29 | reject(e);
30 | }
31 | });
32 | };
33 |
34 | if (util.isRunFlagPresent(process.argv)) {
35 | main();
36 | }
37 |
38 | module.exports = main;
39 |
--------------------------------------------------------------------------------
/LightNodeJs/src/publish.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | const main = async () => {
5 | return new Promise(async (resolve, reject) => {
6 | try {
7 | utils.isValidPrivateKey(PrivateKey);
8 | // Create the client using the validated private key
9 | const client = new StreamrClient({
10 | auth: {
11 | privateKey: PrivateKey,
12 | },
13 | });
14 |
15 | // Create the default stream
16 | const stream = await client.getOrCreateStream({
17 | id: `/light-node-js-example`,
18 | });
19 |
20 | const interval = setInterval(async () => {
21 | const message = {
22 | type: "client:publish",
23 | ts: Date.now(),
24 | };
25 | await client.publish(stream, message);
26 | console.log("Sent successfully: ", message);
27 | resolve({ client, interval });
28 | }, 1000);
29 | } catch (e) {
30 | reject(e);
31 | }
32 | });
33 | };
34 |
35 | if (utils.isRunFlagPresent(process.argv)) {
36 | main();
37 | }
38 |
39 | module.exports = main;
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Streamr usage examples
9 |
10 |
11 | [](https://discord.gg/FVtAph9cvz)
12 |
13 | Applications publish and subscribe to streams via Streamr nodes. In other words, nodes are the access points to the Streamr Network. To connect your application to streams, you interface it with a Streams node. This repository contains examples of pushing or pulling data into or out of the Streamr Network.
14 |
15 | There are two strategies for interfacing applications with Streamr nodes:
16 |
17 | - **Light node:** the node is imported to your application as a library and runs locally as part of your application
18 | - **Broker node:** the node runs separately, and your application connects to it remotely using one of the supported protocols
19 |
20 | Check out the [Developer docs](https://streamr.network/docs) for more more in depth implementation details.
21 |
--------------------------------------------------------------------------------
/LightNodeJs/src/unsubscribeAll.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 | /*
5 | (node:40016) UnhandledPromiseRejectionWarning: TypeError: client.unsubscribeAll is not a function
6 | */
7 | const main = async () => {
8 | utils.isValidPrivateKey(PrivateKey);
9 | // Create the client using the validated private key
10 | const client = new StreamrClient({
11 | auth: {
12 | privateKey: PrivateKey,
13 | },
14 | });
15 |
16 | // Create the default stream
17 | const stream = await client.getOrCreateStream({
18 | id: `/light-node-js-example`,
19 | });
20 | console.log("Stream fetched:", stream.id);
21 | const sub = await client.subscribe({ stream: stream.id });
22 | console.log(`Subscribed to stream ${stream.id}`);
23 | // when no streamId is given, `unsubscribe` will unsubscribe from all streams
24 | const streams = await client.unsubscribe();
25 | console.log(`Unsubscribed from all streams`);
26 | console.log(streams);
27 | await client.destroy;
28 | return stream.id;
29 | };
30 |
31 | if (utils.isRunFlagPresent(process.argv)) {
32 | main();
33 | }
34 |
35 | module.exports = main;
36 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/ws-publish.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require("ws").WebSocket;
2 | const { isRunFlagPresent, getRandomPublisherName } = require("./util");
3 |
4 | const main = async (port = 9091) => {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | const streamId =
8 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example";
9 | const ws = new WebSocket(
10 | `ws://localhost:${port}/streams/${streamId}/publish`
11 | );
12 |
13 | const publisherName = getRandomPublisherName();
14 |
15 | console.log(`Started WS publisher with name ${publisherName}`);
16 |
17 | ws.on("open", () => {
18 | const interval = setInterval(async () => {
19 | const message = {
20 | publisher: publisherName,
21 | type: "broker:ws:publish",
22 | ts: Date.now(),
23 | };
24 |
25 | ws.send(JSON.stringify(message));
26 | console.log("Sent successfully: ", message);
27 | resolve({ interval });
28 | }, 1000);
29 | });
30 | } catch (e) {
31 | reject(e);
32 | }
33 | });
34 | };
35 |
36 | if (isRunFlagPresent(process.argv)) {
37 | main();
38 | }
39 |
40 | module.exports = main;
41 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/mqtt-publish.js:
--------------------------------------------------------------------------------
1 | const mqtt = require("mqtt");
2 | const { isRunFlagPresent, getRandomPublisherName } = require("./util");
3 |
4 | const main = async (port = 9092) => {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | const streamId =
8 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example";
9 | const client = mqtt.connect(`mqtt://localhost:${port}`);
10 |
11 | const publisherName = getRandomPublisherName();
12 |
13 | console.log(`Started MQTT publisher with name ${publisherName}`);
14 |
15 | client.on("connect", () => {
16 | console.log("mqtt listener connected");
17 | const interval = setInterval(async () => {
18 | const message = {
19 | publisher: publisherName,
20 | type: "broker:mqtt:publish",
21 | ts: Date.now(),
22 | };
23 | client.publish(streamId, JSON.stringify(message));
24 | console.log("Sent successfully: ", message);
25 | resolve({ interval });
26 | }, 1000);
27 | });
28 | } catch (e) {
29 | reject(e);
30 | }
31 | });
32 | };
33 |
34 | if (isRunFlagPresent(process.argv)) {
35 | main();
36 | }
37 |
38 | module.exports = main;
39 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/http-publish.js:
--------------------------------------------------------------------------------
1 | const superagent = require("superagent");
2 | const { isRunFlagPresent, getRandomPublisherName } = require("./util");
3 |
4 | const main = async (port = 9093) => {
5 | return new Promise((resolve, reject) => {
6 | try {
7 | const streamId = encodeURIComponent(
8 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example"
9 | );
10 | const url = `http://localhost:${port}/streams/${streamId}`;
11 | const publisherName = getRandomPublisherName();
12 |
13 | console.log(`Started HTTP publisher with name ${publisherName}`);
14 |
15 | const interval = setInterval(async () => {
16 | const message = {
17 | publisher: publisherName,
18 | type: "broker:http:publish",
19 | ts: Date.now(),
20 | };
21 |
22 | const httpResponse = await superagent
23 | .post(url)
24 | .set("Content-Type", "application/json")
25 | .send(message);
26 |
27 | console.log("Sent successfully: ", message);
28 | resolve({ interval, httpResponse });
29 | }, 1000);
30 | } catch (e) {
31 | reject(e);
32 | }
33 | });
34 | };
35 |
36 | if (isRunFlagPresent(process.argv)) {
37 | main();
38 | }
39 |
40 | module.exports = main;
41 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/api-key-auth/mqtt.apiKey.test.js:
--------------------------------------------------------------------------------
1 | const MqttApiPublish = require("../../src/api-key-auth/mqtt-publish");
2 | const MqttApiSubscribe = require("../../src/api-key-auth/mqtt-subscribe");
3 |
4 | let BrokerConfig = require("../../src/api-key-auth/config.json");
5 | const {
6 | expectConsoleLogs,
7 | startBroker,
8 | assignPluginPorts,
9 | } = require("../util");
10 |
11 | describe("MQTT:Api-Key", () => {
12 | let broker;
13 |
14 | BrokerConfig = assignPluginPorts(BrokerConfig, {
15 | http: 7021,
16 | websocket: 7022,
17 | mqtt: 7023,
18 | });
19 |
20 | beforeAll(async () => {
21 | broker = await startBroker(BrokerConfig);
22 | }, 5 * 1000);
23 |
24 | afterAll(async () => {
25 | await broker.stop();
26 | });
27 |
28 | beforeEach(() => {
29 | console.log = jest.fn();
30 | });
31 |
32 | it("should exercise the `publish` example", async () => {
33 | const { interval } = await MqttApiPublish(BrokerConfig.plugins.mqtt.port);
34 | expectConsoleLogs(["mqtt listener connected"]);
35 | clearInterval(interval);
36 | });
37 |
38 | it("should exercise the `subscribe` example", async () => {
39 | await MqttApiSubscribe(BrokerConfig.plugins.mqtt.port);
40 | expectConsoleLogs(["mqtt subscribe connected"]);
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/mqtt.test.js:
--------------------------------------------------------------------------------
1 | const MqttPublish = require("../src/mqtt-publish");
2 | const MqttSubscribe = require("../src/mqtt-subscribe");
3 |
4 | let BrokerConfig = require("../src/config.json");
5 | const {
6 | TimeoutMs,
7 | expectConsoleLogs,
8 | startBroker,
9 | assignPluginPorts,
10 | } = require("./util");
11 |
12 | describe("MQTT", () => {
13 | let broker;
14 |
15 | BrokerConfig = assignPluginPorts(BrokerConfig, {
16 | http: 4021,
17 | websocket: 4022,
18 | mqtt: 4023,
19 | });
20 |
21 | beforeAll(async () => {
22 | broker = await startBroker(BrokerConfig);
23 | }, 5 * 1000);
24 |
25 | afterAll(async () => {
26 | await broker.stop();
27 | });
28 |
29 | beforeEach(() => {
30 | console.log = jest.fn();
31 | });
32 |
33 | it("should exercise the `subscribe` example", async () => {
34 | await MqttSubscribe(BrokerConfig.plugins.mqtt.port);
35 | expectConsoleLogs(["mqtt listener connected"]);
36 | });
37 |
38 | it(
39 | "should exercise the `publish` example",
40 | async () => {
41 | const { interval } = await MqttPublish(BrokerConfig.plugins.mqtt.port);
42 | expectConsoleLogs(["mqtt listener connected", "Sent successfully: "]);
43 | clearInterval(interval);
44 | },
45 | TimeoutMs
46 | );
47 | });
48 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/api-key-auth/ws.apiKey.test.js:
--------------------------------------------------------------------------------
1 | const WsApiPublish = require("../../src/api-key-auth/ws-publish");
2 | const WsApiSubscribe = require("../../src/api-key-auth/ws-subscribe");
3 |
4 | let BrokerConfig = require("../../src/api-key-auth/config.json");
5 | const {
6 | expectConsoleLogs,
7 | startBroker,
8 | assignPluginPorts,
9 | } = require("../util");
10 |
11 | describe("WS:Api-Key", () => {
12 | let broker;
13 |
14 | BrokerConfig = assignPluginPorts(BrokerConfig, {
15 | http: 9021,
16 | websocket: 9022,
17 | mqtt: 9023,
18 | });
19 |
20 | beforeAll(async () => {
21 | broker = await startBroker(BrokerConfig);
22 | }, 5 * 1000);
23 |
24 | afterAll(async () => {
25 | await broker.stop();
26 | });
27 |
28 | beforeEach(() => {
29 | console.log = jest.fn();
30 | });
31 |
32 | it("should exercise the `subscribe` example", async () => {
33 | WsApiSubscribe(BrokerConfig.plugins.websocket.port);
34 | expectConsoleLogs(["websocket listener connected"]);
35 | });
36 |
37 | it("should exercise the `publish` example", async () => {
38 | const { interval } = await WsApiPublish(
39 | BrokerConfig.plugins.websocket.port
40 | );
41 | expectConsoleLogs(["Sent successfully: "]);
42 | clearInterval(interval);
43 | });
44 | });
45 |
--------------------------------------------------------------------------------
/LightNodeJs/src/setPermissions.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient, StreamPermission } = require("streamr-client");
2 | const utils = require("./utils.js");
3 | const { PrivateKey } = require("./config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 | // Create the client using the validated private key
8 | const client = new StreamrClient({
9 | auth: {
10 | privateKey: PrivateKey,
11 | },
12 | });
13 |
14 | const { address } = StreamrClient.generateEthereumAccount();
15 |
16 | await client.setPermissions(
17 | {
18 | streamId: `${await client.getAddress()}/light-node-js-example/permissions`,
19 | assignments: [
20 | {
21 | user: address,
22 | permissions: [StreamPermission.SUBSCRIBE],
23 | },
24 | ],
25 | },
26 | {
27 | streamId: `${await client.getAddress()}/light-node-js-example`,
28 | assignments: [
29 | {
30 | user: address,
31 | permissions: [StreamPermission.PUBLISH],
32 | },
33 | {
34 | public: true,
35 | permissions: [StreamPermission.SUBSCRIBE],
36 | },
37 | ],
38 | }
39 | );
40 |
41 | await client.destroy();
42 | };
43 |
44 | if (utils.isRunFlagPresent(process.argv)) {
45 | main();
46 | }
47 |
48 | module.exports = main;
49 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/publish.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient } = require("streamr-client");
2 | const utils = require("../utils.js");
3 | const { PrivateKey } = require("../config.js");
4 |
5 | const main = async () => {
6 | return new Promise(async (resolve, reject) => {
7 | try {
8 | utils.isValidPrivateKey(PrivateKey);
9 | // Create the client using the validated private key
10 | const client = new StreamrClient({
11 | auth: {
12 | privateKey: PrivateKey,
13 | },
14 | });
15 |
16 | // Create the default stream
17 | const stream = await client.getOrCreateStream({
18 | id: `/light-node-js-example`,
19 | });
20 |
21 | const sub = await client.subscribe({ stream: stream.id }, (message) => {
22 | console.log("client.subscribe:", message);
23 | });
24 |
25 | const interval = setInterval(async () => {
26 | const message = {
27 | type: "stream:publish",
28 | ts: Date.now(),
29 | };
30 | await stream.publish(message);
31 | console.log("Sent successfully: ", message);
32 | resolve({ client, interval });
33 | }, 1000);
34 | } catch (e) {
35 | reject(e);
36 | }
37 | });
38 | };
39 |
40 | if (utils.isRunFlagPresent(process.argv)) {
41 | main();
42 | }
43 |
44 | module.exports = main;
45 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/api-key-auth/ws-publish.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require("ws").WebSocket;
2 | const BrokerConfig = require("./config.json");
3 | const { isRunFlagPresent, getRandomPublisherName } = require("../util");
4 |
5 | const API_KEY = BrokerConfig.apiAuthentication.keys[0];
6 |
7 | const main = async (PORT = 7071) => {
8 | return new Promise((resolve, reject) => {
9 | try {
10 | const streamId =
11 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example";
12 | const ws = new WebSocket(
13 | `ws://localhost:${PORT}/streams/${streamId}/publish?apiKey=${API_KEY}`
14 | );
15 |
16 | const publisherName = getRandomPublisherName();
17 |
18 | console.log(`Started WS publisher with name ${publisherName}`);
19 |
20 | ws.on("open", () => {
21 | const interval = setInterval(async () => {
22 | const message = {
23 | publisher: publisherName,
24 | type: "broker:ws:publish",
25 | ts: Date.now(),
26 | };
27 |
28 | ws.send(JSON.stringify(message));
29 | console.log("Sent successfully: ", message);
30 | resolve({ interval });
31 | }, 1000);
32 | });
33 | } catch (e) {
34 | reject(e);
35 | }
36 | });
37 | };
38 |
39 | if (isRunFlagPresent(process.argv)) {
40 | main();
41 | }
42 |
43 | module.exports = main;
44 |
--------------------------------------------------------------------------------
/BrokerApiPython/mqtt-subscribe.py:
--------------------------------------------------------------------------------
1 | import secrets
2 | import random
3 | import time
4 | import os
5 | from dotenv import load_dotenv
6 | from paho.mqtt import client as mqtt_client
7 |
8 | load_dotenv()
9 |
10 | broker = '143.215.112.253'
11 | port = 8082
12 | streamID = "0xDFbc82D80B743DC4Ab8dafBC9AfFc55f2245Fa7E/mqtt-python"
13 | # generate client ID with pub prefix randomly
14 | PrivateKey = os.getenv("PrivateKey")
15 |
16 | def connect_mqtt():
17 | def on_connect(client, userdata, flags, rc):
18 | if rc == 0:
19 | print("Connected to MQTT Broker!")
20 | else:
21 | print("Failed to connect, return code %d\n", rc)
22 |
23 | client = mqtt_client.Client(PrivateKey)
24 | client.on_connect = on_connect
25 | client.connect(broker, port)
26 | return client
27 |
28 | def subscribe(client):
29 | msg_count = 0
30 | while True:
31 | time.sleep(1)
32 | msg = f"messages: {msg_count}"
33 | result = client.subscribe(streamID)
34 | # result: [0, 1]
35 | status = result[0]
36 | if status == 0:
37 | print(f"Send `{msg}` to topic `{streamID}`")
38 | else:
39 | print(f"Failed to send message to topic {streamID}")
40 | msg_count += 1
41 |
42 | def run():
43 | client = connect_mqtt()
44 | client.loop_start()
45 | subscribe(client)
46 |
47 |
48 | if __name__ == '__main__':
49 | run()
50 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/api-key-auth/http-publish.js:
--------------------------------------------------------------------------------
1 | const superagent = require("superagent");
2 | const BrokerConfig = require("./config.json");
3 | const { isRunFlagPresent, getRandomPublisherName } = require("../util");
4 |
5 | const API_KEY = BrokerConfig.apiAuthentication.keys[0];
6 |
7 | const main = async (PORT = 7073) => {
8 | return new Promise((resolve, reject) => {
9 | try {
10 | const streamId = encodeURIComponent(
11 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example"
12 | );
13 | const url = `http://localhost:${PORT}/streams/${streamId}`;
14 |
15 | const publisherName = getRandomPublisherName();
16 |
17 | console.log(`Started HTTP publisher with name ${publisherName}`);
18 |
19 | const interval = setInterval(async () => {
20 | const message = {
21 | publisher: publisherName,
22 | type: "broker:http:publish",
23 | ts: Date.now(),
24 | };
25 |
26 | const httpResponse = await superagent
27 | .post(url)
28 | .set("Authorization", `bearer ${API_KEY}`)
29 | .set("Content-Type", "application/json")
30 | .send(message);
31 |
32 | console.log("Sent successfully: ", message);
33 | resolve({ interval, httpResponse });
34 | }, 1000);
35 | } catch (e) {
36 | reject(e);
37 | }
38 | });
39 | };
40 |
41 | if (isRunFlagPresent(process.argv)) {
42 | main();
43 | }
44 |
45 | module.exports = main;
46 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/permissions/grantPermissions.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient, StreamPermission } = require("streamr-client");
2 | const utils = require("../../utils.js");
3 | const { PrivateKey } = require("../../config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 | // Create the client using the validated private key
8 | const client = new StreamrClient({
9 | auth: {
10 | privateKey: PrivateKey,
11 | },
12 | });
13 |
14 | // Create the default stream
15 | const stream = await client.getOrCreateStream({
16 | id: `/light-node-js-example/permissions`,
17 | });
18 |
19 | console.log(`Stream ${stream.id} created`);
20 |
21 | const { address } = StreamrClient.generateEthereumAccount();
22 | // granting a user permission
23 | await stream.grantPermissions({
24 | user: address,
25 | permissions: [StreamPermission.SUBSCRIBE],
26 | });
27 | console.log("Subscribe user permission granted for stream", stream.id);
28 | // or granting public permissions
29 | // await stream.grantPermissions({ public: true, permissions: [StreamPermission.SUBSCRIBE] });
30 | console.log("Subscribe public permission granted for stream", stream.id);
31 | const permissions = await stream.getPermissions();
32 | console.log("Permissions", permissions);
33 |
34 | await client.destroy();
35 | return stream.id;
36 | };
37 |
38 | if (utils.isRunFlagPresent(process.argv)) {
39 | main();
40 | }
41 |
42 | module.exports = main;
43 |
--------------------------------------------------------------------------------
/Webpack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "streamr-client-webpack-example",
3 | "version": "0.0.0",
4 | "description": "Example of how streamr-client can be included in webpack projects",
5 | "scripts": {
6 | "build": "NODE_ENV=production webpack --mode=production --progress",
7 | "dev": "webpack --progress --colors --watch",
8 | "build-with-parent": "cp -Rpfv ../../dist ./node_modules/streamr-client/ && rm node_modules/streamr-client/package.json; cp ../../package.json ./node_modules/streamr-client/package.json && npm run build"
9 | },
10 | "engines": {
11 | "node": ">= 8"
12 | },
13 | "author": "Streamr",
14 | "license": "AGPL-3.0-or-later",
15 | "devDependencies": {
16 | "@babel/cli": "^7.7.7",
17 | "@babel/core": "^7.7.7",
18 | "@babel/plugin-proposal-class-properties": "^7.7.4",
19 | "@babel/plugin-transform-classes": "^7.7.4",
20 | "@babel/plugin-transform-modules-commonjs": "^7.7.5",
21 | "@babel/plugin-transform-runtime": "^7.14.5",
22 | "@babel/preset-env": "^7.14.8",
23 | "babel-loader": "^8.0.6",
24 | "babel-plugin-add-module-exports": "^1.0.2",
25 | "babel-plugin-transform-class-properties": "^6.24.1",
26 | "babel-plugin-transform-runtime": "^6.23.0",
27 | "core-js": "^2.6.11",
28 | "webpack": "^4.41.5",
29 | "webpack-cli": "^3.3.10"
30 | },
31 | "#": "Update core-js -> 3.6.2, after releasing new version of client",
32 | "dependencies": {
33 | "@babel/runtime": "^7.11.2",
34 | "streamr-client": "latest"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/BrokerApiNode/src/api-key-auth/mqtt-publish.js:
--------------------------------------------------------------------------------
1 | const mqtt = require("mqtt");
2 | const BrokerConfig = require("./config.json");
3 | const { isRunFlagPresent, getRandomPublisherName } = require("../util");
4 |
5 | const API_KEY = BrokerConfig.apiAuthentication.keys[0];
6 |
7 | const main = async (PORT = 7072) => {
8 | return new Promise((resolve, reject) => {
9 | try {
10 | const streamId =
11 | "0x00de714cbad811af322f539a043ec71eab7fa3a5/broker-example";
12 | const client = mqtt.connect(`mqtt://localhost:${PORT}`, {
13 | username: "",
14 | password: API_KEY,
15 | });
16 |
17 | const publisherName = getRandomPublisherName();
18 |
19 | console.log(`Started MQTT publisher with name ${publisherName}`);
20 |
21 | client.on("connect", () => {
22 | console.log("mqtt listener connected");
23 | const interval = setInterval(async () => {
24 | const message = {
25 | publisher: publisherName,
26 | type: "broker:mqtt:publish",
27 | ts: Date.now(),
28 | };
29 | const publishResponse = client.publish(
30 | streamId,
31 | JSON.stringify(message)
32 | );
33 |
34 | console.log("Sent successfully: ", message);
35 | }, 1000);
36 | resolve({ interval });
37 | });
38 | } catch (e) {
39 | reject(e);
40 | }
41 | });
42 | };
43 |
44 | if (isRunFlagPresent(process.argv)) {
45 | main();
46 | }
47 |
48 | module.exports = main;
49 |
--------------------------------------------------------------------------------
/Tutorials/mqtt/scripts/01-CreateStreamAndAssignPermissions.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient, StreamPermission } = require('streamr-client')
2 | // This will need to be replaced with a private key that has MATIC tokens (Polygon blockchain gas token)
3 | const PrivateKey = '...'
4 | // See README.md, 1.2 - Initial broker setup
5 | const BrokerNodeAddress = '...'
6 |
7 | const main = async () => {
8 | // Create the Streamr Client instance with its own private key
9 | const streamr = new StreamrClient({
10 | auth: {
11 | privateKey: PrivateKey,
12 | }
13 | });
14 |
15 | // Create the stream
16 | const stream = await streamr.getOrCreateStream({
17 | id: '/sensor/firehose',
18 | })
19 | // Grant permissions to the broker node on the stream
20 | // Requires MATIC tokens (Polygon blockchain gas token)
21 | await streamr.setPermissions({
22 | streamId: stream.id,
23 | assignments: [
24 | {
25 | user: BrokerNodeAddress,
26 | permissions: [
27 | StreamPermission.PUBLISH,
28 | StreamPermission.SUBSCRIBE
29 | ]
30 | }
31 | ]
32 | })
33 | // Check the granted permissions
34 | // Temporary delay for The Graph indexing delay (not necessary, but nice for quick console logging!)
35 | await new Promise(r => setTimeout(r, 5000));
36 |
37 | const permissions = await stream.getPermissions()
38 | console.log(stream.id, permissions)
39 | }
40 | main()
41 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/permissions/hasPermission.js:
--------------------------------------------------------------------------------
1 | const { StreamPermission, StreamrClient } = require("streamr-client");
2 | const utils = require("../../utils.js");
3 | const { PrivateKey } = require("../../config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 | // Create the client using the validated private key
8 | const client = new StreamrClient({
9 | auth: {
10 | privateKey: PrivateKey,
11 | },
12 | });
13 |
14 | // Create the default stream
15 | const stream = await client.getOrCreateStream({
16 | id: `/light-node-js-example/permissions`,
17 | });
18 |
19 | console.log(`Stream ${stream.id} created`);
20 | const { address } = StreamrClient.generateEthereumAccount();
21 | // grant public permissions for subscribe
22 | let hasPermission = await stream.hasPermission({
23 | user: address,
24 | permission: StreamPermission.SUBSCRIBE,
25 | allowPublic: true,
26 | });
27 |
28 | console.log(`hasPermission? ${hasPermission ? "yes" : "no"}`);
29 |
30 | await stream.grantPermissions({
31 | user: address,
32 | permissions: [StreamPermission.SUBSCRIBE],
33 | });
34 |
35 | hasPermission = await stream.hasPermission({
36 | user: address,
37 | permission: StreamPermission.SUBSCRIBE,
38 | allowPublic: true,
39 | });
40 |
41 | console.log(`hasPermission? ${hasPermission ? "yes" : "no"}`);
42 | await client.destroy();
43 | return stream.id;
44 | };
45 |
46 | if (utils.isRunFlagPresent(process.argv)) {
47 | main();
48 | }
49 |
50 | module.exports = main;
51 |
--------------------------------------------------------------------------------
/BrokerApiPython/mqtt-publish.py:
--------------------------------------------------------------------------------
1 | import secrets
2 | import random
3 | import time
4 | import os
5 | from dotenv import load_dotenv
6 | from paho.mqtt import client as mqtt_client
7 | from coincurve import PublicKey
8 | from sha3 import keccak_256
9 | from eth_keys import keys
10 | from eth_utils import decode_hex
11 |
12 |
13 | load_dotenv()
14 |
15 | # insert broker name, port number, and streamID
16 | broker = '143.215.112.253'
17 | port = 8082
18 | streamID = "0xDFbc82D80B743DC4Ab8dafBC9AfFc55f2245Fa7E/mqtt-python"
19 |
20 | # generate client ID with pub prefix randomly
21 | PrivateKey = os.getenv("PrivateKey")
22 |
23 | def connect_mqtt():
24 | def on_connect(client, userdata, flags, rc):
25 | if rc == 0:
26 | print("Connected to MQTT Broker!")
27 | else:
28 | print("Failed to connect, return code %d\n", rc)
29 |
30 | client = mqtt_client.Client(PrivateKey)
31 | client.on_connect = on_connect
32 | client.connect(broker, port)
33 | return client
34 |
35 |
36 | def publish(client):
37 | msg_count = 0
38 | while True:
39 | time.sleep(1)
40 | msg = f"messages: {msg_count}"
41 | result = client.publish(streamID, msg)
42 | # result: [0, 1]
43 | status = result[0]
44 | if status == 0:
45 | print(f"Send `{msg}` to topic `{streamID}`")
46 | else:
47 | print(f"Failed to send message to topic {streamID}")
48 | msg_count += 1
49 |
50 |
51 | def run():
52 | client = connect_mqtt()
53 | client.loop_start()
54 | publish(client)
55 |
56 |
57 | if __name__ == '__main__':
58 | run()
59 |
--------------------------------------------------------------------------------
/LightNodeJs/src/stream/permissions/revokePermissions.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient, StreamPermission } = require("streamr-client");
2 | const utils = require("../../utils.js");
3 | const { PrivateKey } = require("../../config.js");
4 |
5 | const main = async () => {
6 | utils.isValidPrivateKey(PrivateKey);
7 | // Create the client using the validated private key
8 | const client = new StreamrClient({
9 | auth: {
10 | privateKey: PrivateKey,
11 | },
12 | });
13 |
14 | // Create the default stream
15 | const stream = await client.getOrCreateStream({
16 | id: `/light-node-js-example/permissions`,
17 | });
18 |
19 | const { address } = StreamrClient.generateEthereumAccount();
20 |
21 | // grant user permission
22 | await stream.grantPermissions({
23 | user: address,
24 | permissions: [StreamPermission.SUBSCRIBE],
25 | });
26 | console.log("Granted user permission for subscribe");
27 | let permissions = await stream.getPermissions();
28 | console.log("Permission granted", permissions);
29 | // revoke the user permission
30 | await stream.revokePermissions({
31 | user: address,
32 | permissions: [StreamPermission.SUBSCRIBE],
33 | });
34 | // or for a public permission revoke:
35 | // await stream.revokePermissions({ public: true, permissions: [StreamPermission.SUBSCRIBE] });
36 | console.log("Revoked user permission");
37 | permissions = await stream.getPermissions();
38 | console.log("Permission revoked", permissions);
39 | await client.destroy();
40 | return stream.id;
41 | };
42 |
43 | if (utils.isRunFlagPresent(process.argv)) {
44 | main();
45 | }
46 |
47 | module.exports = main;
48 |
--------------------------------------------------------------------------------
/RaspberryPi/index.js:
--------------------------------------------------------------------------------
1 | const StreamrClient = require("streamr-client");
2 | const fs = require("fs");
3 |
4 | require("dotenv").config();
5 |
6 | const client = new StreamrClient({
7 | auth: {
8 | privateKey: process.env.ETHEREUM_PrivateKey,
9 | },
10 | });
11 |
12 | var currentCPUInfo = { total: 0, active: 0 };
13 | var lastCPUInfo = { total: 0, active: 0 };
14 |
15 | const calculateCPUPercentage = (oldVals, newVals) => {
16 | var totalDiff = newVals.total - oldVals.total;
17 | var activeDiff = newVals.active - oldVals.active;
18 | return Math.ceil((activeDiff / totalDiff) * 100);
19 | };
20 |
21 | const getCPUInfo = () => {
22 | lastCPUInfo.active = currentCPUInfo.active;
23 | lastCPUInfo.idle = currentCPUInfo.idle;
24 | lastCPUInfo.total = currentCPUInfo.total;
25 |
26 | fs.readFile("/proc/stat", "utf8", function (err, data) {
27 | var lines = data.split("\n");
28 | var cpuTimes = lines[0].match(/[0-9]+/gi);
29 | currentCPUInfo.total = 0;
30 | // We'll count both idle and iowait as idle time
31 | currentCPUInfo.idle = parseInt(cpuTimes[3]) + parseInt(cpuTimes[4]);
32 | for (var i = 0; i < cpuTimes.length; i++) {
33 | currentCPUInfo.total += parseInt(cpuTimes[i]);
34 | }
35 | currentCPUInfo.active = currentCPUInfo.total - currentCPUInfo.idle;
36 | currentCPUInfo.percentUsed = calculateCPUPercentage(
37 | lastCPUInfo,
38 | currentCPUInfo
39 | );
40 |
41 | console.log("Current CPU Usage: " + currentCPUInfo.percentUsed + "%");
42 |
43 | client.publish("STREAM-ID", {
44 | cpuUsage: "Current CPU Usage: " + currentCPUInfo.percentUsed + "%",
45 | });
46 | });
47 | };
48 |
49 | setInterval(getCPUInfo, 1000);
50 |
--------------------------------------------------------------------------------
/BrokerApiNode/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "streamr-broker-node-example",
3 | "version": "0.0.1",
4 | "description": "Using broker APIs in node",
5 | "main": "node.js",
6 | "engines": {
7 | "npm": ">=8.0.0",
8 | "node": ">=16.0.0"
9 | },
10 | "scripts": {
11 | "test": "jest --runInBand",
12 | "prettier": "prettier --write src test",
13 | "broker:start": "streamr-broker src/config.json",
14 | "broker:start-api-key": "streamr-broker src/api-key-auth/config.json",
15 | "http:publish": "node --experimental-json-modules src/http-publish.js --run",
16 | "http:api-key-publish": "node --experimental-json-modules src/api-key-auth/http-publish.js --run",
17 | "ws:publish": "node --experimental-json-modules src/ws-publish.js --run",
18 | "ws:api-key-publish": "node --experimental-json-modules src/api-key-auth/ws-publish.js --run",
19 | "ws:subscribe": "node --experimental-json-modules src/ws-subscribe.js --run",
20 | "ws:api-key-subscribe": "node --experimental-json-modules src/api-key-auth/ws-subscribe.js --run",
21 | "mqtt:publish": "node --experimental-json-modules src/mqtt-publish.js --run",
22 | "mqtt:api-key-publish": "node --experimental-json-modules src/api-key-auth/mqtt-publish.js --run",
23 | "mqtt:subscribe": "node --experimental-json-modules src/mqtt-subscribe.js --run",
24 | "mqtt:api-key-subscribe": "node --experimental-json-modules src/api-key-auth/mqtt-subscribe.js --run"
25 | },
26 | "dependencies": {
27 | "ethers": "^5.4.7",
28 | "mqtt": "^4.2.8",
29 | "streamr-broker": "^31.0.2",
30 | "superagent": "^6.1.0",
31 | "unique-names-generator": "^4.7.1",
32 | "ws": "^8.2.2"
33 | },
34 | "devDependencies": {
35 | "jest": "^27.3.1",
36 | "prettier": "^2.5.1"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/LightNodeJs/src/anon.js:
--------------------------------------------------------------------------------
1 | const { StreamrClient, StreamPermission } = require("streamr-client");
2 |
3 | const utils = require("./utils.js");
4 | const { PrivateKey } = require("./config.js");
5 |
6 | const main = async () => {
7 | utils.isValidPrivateKey(PrivateKey);
8 |
9 | // Create the client using the validated private key
10 | const authClient = new StreamrClient({
11 | auth: {
12 | privateKey: PrivateKey,
13 | },
14 | });
15 |
16 | const stream = await authClient.getOrCreateStream({
17 | id: "/light-node-js-example/anon",
18 | });
19 |
20 | console.log("created/fetched stream with id", stream.id);
21 | // public permissions per each action are required to interact with the anon streamr-client
22 | const permissions = await stream.getPermissions();
23 | if (
24 | !permissions.public ||
25 | !permissions.public.includes(StreamPermission.SUBSCRIBE)
26 | ) {
27 | await stream.grantPermissions({
28 | public: true,
29 | permissions: [StreamPermission.SUBSCRIBE],
30 | });
31 | console.log("granted public subscribe permission on stream", stream.id);
32 | }
33 | // Create the client using no private key
34 | const anonClient = new StreamrClient();
35 |
36 | // this client can subscribe to public streams
37 | anonClient.subscribe(stream.id, (msg) => {
38 | console.log("Received:", msg);
39 | });
40 |
41 | console.log("anon client subscribed to stream", stream.id);
42 | setInterval(async () => {
43 | const message = {
44 | type: "client:publish",
45 | ts: Date.now(),
46 | };
47 | await authClient.publish(stream.id, message);
48 |
49 | console.log("Sent:", message);
50 | }, 1000);
51 | };
52 |
53 | if (utils.isRunFlagPresent(process.argv)) {
54 | main();
55 | }
56 |
57 | module.exports = main;
58 |
--------------------------------------------------------------------------------
/BrokerApiNode/test/util.js:
--------------------------------------------------------------------------------
1 | const createBroker = require("streamr-broker/dist/src/broker.js").createBroker;
2 | const { Wallet } = require("ethers");
3 |
4 | exports.TimeoutMs = 30 * 1000;
5 |
6 | (exports.wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))),
7 | (exports.expectConsoleLogs = (logs, ignoreSorting = false) => {
8 | // only evaluates the first element of the console log, if given comma-separated
9 | for (let i = 0; i < logs.length; i++) {
10 | if (
11 | // ignore the ethers warning about api usage
12 | console.log.mock.calls[i][0] === "========= NOTICE =========" ||
13 | //
14 | console.log.mock.calls[i][0] ===
15 | "Request-Rate Exceeded (this message will not be repeated)"
16 | ) {
17 | logs.splice(i, 1);
18 | continue;
19 | }
20 | if (ignoreSorting) {
21 | // evaluate that the value exists in the log for highly-async cases, like resend
22 | //expect(console.log.mock.calls[i].includes(logs[i])).toBe(true)
23 | expect(logs.includes(console.log.mock.calls[i][0])).toBe(true);
24 | } else {
25 | // match each value in it's right position
26 | expect(console.log.mock.calls[i][0]).toBe(logs[i]);
27 | }
28 | }
29 | });
30 |
31 | exports.TimeoutMs = 60 * 1000;
32 |
33 | exports.startBroker = async (config) => {
34 | const broker = await createBroker({
35 | ...config,
36 | client: {
37 | ...config.client,
38 | auth: { privateKey: Wallet.createRandom().privateKey },
39 | },
40 | });
41 | await broker.start();
42 | return broker;
43 | };
44 |
45 | exports.assignPluginPorts = (config, ports) => {
46 | config.plugins.websocket.port = ports.websocket;
47 | config.plugins.mqtt.port = ports.mqtt;
48 | config.httpServer.port = ports.http;
49 | return config;
50 | };
51 |
--------------------------------------------------------------------------------
/Browser/README.md:
--------------------------------------------------------------------------------
1 | # Web
2 |
3 | This example demostrates how to use the Streamr Client with plain HTML. These examples use the web version of the Streamr JS client, pulled from the external [Unpkg service](https://unpkg.com/streamr-client).
4 |
5 | ## Setting Up
6 | You can install [live-server](https://github.com/tapio/live-server) and serve the `www` folder to run the examples locally with the following commands:
7 | ```shell
8 | $ npm install
9 | $ npm start
10 | ```
11 |
12 | ### Stream Publish web example
13 |
14 | This example publishes a message to a stream, from inside the browser. It requires private key authentication and a pre-existing stream that can be created in the [Streamr Core UI](https://streamr.network/core)
15 |
16 | - Replace the  with your private key.
17 | - Replace the  with your stream ID.
18 |
19 | ### Stream Subscribe web example
20 |
21 | This example subsribes to the [Helsinki Tram GPS stream](https://streamr.network/marketplace/products/31e8df5243ce49cfa250002f60b73e475f39b44723ca4fbcbf695198d19c6b08).
22 |
23 | ### Metamask integration example
24 |
25 | Shows how to authenticate to Streamr using Metamask and can create new streams and export the session key if needed. It requires Metamask to be installed on a modern browser.
26 |
27 | ## Running examples
28 |
29 | Open the html files in your browser using `open web-example-publish.html` or `open web-example-subscribe.html`.
30 |
31 | **IMPORTANT:** For the Metamask example, you will need to install [live-server](https://github.com/tapio/live-server) and run the html file with it using `live-server web-example-metamask.html`.
32 |
--------------------------------------------------------------------------------
/LightNodeJs/README.md:
--------------------------------------------------------------------------------
1 | ## Light Node (JS)
2 |
3 | This example demostrates how to use the Streamr Client in a Node environment. Node version 14/16 or higher is recommended.
4 |
5 |
6 | - [Existing docs](https://github.com/streamr-dev/network-monorepo/blob/main/packages/client/README.md)
7 | - [Examples directory](https://github.com/streamr-dev/examples/blob/ECODR-34-broker-and-client/NodeJs/src/client/)
8 | - [Brubeck Client](https://github.com/streamr-dev/network-monorepo/blob/NET-201-brubeck-client/)
9 |
10 | The Streamr JavaScript Client imports and runs a Streamr light node as a library which participates in the Streamr Network.
11 |
12 | - Install and setup (NodeJS and browser)
13 | - StreamrClient constructor
14 | - `client` class
15 | - connect
16 | - subscribe
17 | - unsubscribe
18 | - unsubscribeAll
19 | - getSubscriptions
20 | - resend
21 | - createStream
22 | - getStream
23 | - getOrCreateStream
24 | - publish
25 | - `stream` class
26 | - stream.addToStorageNode
27 | - stream.getPermissions
28 | - stream.hasPermissions
29 | - stream.grantPermission
30 | - stream.revokePermission
31 | - stream.publish
32 | - data unions
33 |
34 |
35 | ______________________________________________________
36 |
37 | Running the examples:
38 | ```shell
39 | $ npm run subscribe
40 | $ npm run unsubscribe
41 | $ npm run unsubscribeAll
42 | $ npm run getSubscriptions
43 | $ npm run resend
44 | $ npm run createStream
45 | $ npm run getStream
46 | $ npm run getOrCreateStream
47 | $ npm run publish
48 | $ npm run searchStream
49 | $ npm run stream:addToStorageNode
50 | $ npm run stream:publish
51 | $ npm run stream:delete
52 | $ npm run stream:getStorageNodes
53 | $ npm run stream:removeFromStorageNode
54 | $ npm run stream:hasPermission
55 | $ npm run stream:getPermissions
56 | $ npm run stream:grantPermissions
57 | $ npm run stream:revokePermissions
58 | $ npm run stream:update
59 | ```
--------------------------------------------------------------------------------
/LightNodeJs/src/resend.js:
--------------------------------------------------------------------------------
1 | const {
2 | STREAMR_STORAGE_NODE_GERMANY,
3 | StreamrClient,
4 | } = require("streamr-client");
5 | const utils = require("./utils.js");
6 | const { PrivateKey } = require("./config.js");
7 | const main = async () => {
8 | utils.isValidPrivateKey(PrivateKey);
9 | // Create the client using the validated private key
10 | const client = new StreamrClient({
11 | auth: {
12 | privateKey: PrivateKey,
13 | },
14 | });
15 |
16 | // Create the default stream
17 | const stream = await client.getOrCreateStream({
18 | id: `/light-node-js-example`,
19 | });
20 |
21 | const storageNodes = await stream.getStorageNodes();
22 | if (storageNodes.length === 0) {
23 | await stream.addToStorageNode(STREAMR_STORAGE_NODE_GERMANY);
24 | console.log("Stream added to storage node");
25 | }
26 |
27 | await stream.publish({ id: 0 });
28 | await stream.publish({ id: 1 });
29 | await stream.publish({ id: 2 });
30 |
31 | // ensure that the stream is being stored!
32 | console.log("Stream fetched:", stream.id);
33 |
34 | const subscription = await client.subscribe(
35 | {
36 | stream: stream.id,
37 | resend: {
38 | // should see the recently send messages, along with 3 identical ones from storage
39 | last: 6,
40 | },
41 | },
42 | (message) => {
43 | // Do something with the messages as they are received
44 | console.log(JSON.stringify(message));
45 | }
46 | );
47 |
48 | const resend = await client.resend(
49 | stream.id,
50 | {
51 | // should see the recently send messages, along with 3 identical ones from storage
52 | last: 6,
53 | },
54 | (message) => {
55 | // Do something with the messages as they are received
56 | console.log(JSON.stringify(message));
57 | }
58 | );
59 | };
60 |
61 | if (utils.isRunFlagPresent(process.argv)) {
62 | main();
63 | }
64 |
65 | module.exports = main;
66 |
--------------------------------------------------------------------------------
/LightNodeJs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "streamr-lightnodejs-examples",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "engines": {
7 | "npm": ">=8.0.0",
8 | "node": ">=16.0.0"
9 | },
10 | "scripts": {
11 | "test": "jest --runInBand",
12 | "prettier": "prettier --write src",
13 | "anon": "node src/anon.js --run",
14 | "subscribe": "node src/subscribe.js --run",
15 | "unsubscribe": "node src/unsubscribe.js --run",
16 | "unsubscribeAll": "node src/unsubscribeAll.js --run",
17 | "getSubscriptions": "node src/getSubscriptions.js --run",
18 | "resend": "node src/resend.js --run",
19 | "createStream": "node src/createStream.js --run",
20 | "getStream": "node src/getStream.js --run",
21 | "getOrCreateStream": "node src/getOrCreateStream.js --run",
22 | "publish": "node src/publish.js --run",
23 | "searchStream": "node src/searchStream.js --run",
24 | "stream:addToStorageNode": "node src/stream/addToStorageNode.js --run",
25 | "stream:publish": "node src/stream/publish.js --run",
26 | "stream:delete": "node src/stream/delete.js --run",
27 | "stream:getStorageNodes": "node src/stream/getStorageNodes.js --run",
28 | "stream:removeFromStorageNode": "node src/stream/removeFromStorageNode.js --run",
29 | "stream:hasPermission": "node src/stream/permissions/hasPermission.js --run",
30 | "stream:getPermissions": "node src/stream/permissions/getPermissions.js --run",
31 | "stream:grantPermissions": "node src/stream/permissions/grantPermissions.js --run",
32 | "stream:revokePermissions": "node src/stream/permissions/revokePermissions.js --run",
33 | "setPermissions": "node src/setPermissions.js --run",
34 | "stream:update": "node src/stream/update.js --run",
35 | "du:create": "node src/data-union/create.js --run"
36 | },
37 | "dependencies": {
38 | "ethers": "^5.4.7",
39 | "streamr-client": "7.1.0"
40 | },
41 | "author": "",
42 | "license": "ISC",
43 | "devDependencies": {
44 | "jest": "^27.3.1",
45 | "prettier": "^2.5.1"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Webpack/src/index.js:
--------------------------------------------------------------------------------
1 | import StreamrClient from 'streamr-client'
2 |
3 | const log = (msg) => {
4 | const elem = document.createElement('p')
5 | elem.innerHTML = msg
6 | document.body.appendChild(elem)
7 | }
8 |
9 | // REPLACE THIS WITH YOUR OWN PRIVATE KEY
10 | const PrivateKey = 'MY-PRIVATE-KEY'
11 |
12 | let client;
13 |
14 | if (PrivateKey === 'MY-PRIVATE-KEY') {
15 | log('You need to set your private key in the script')
16 | } else {
17 | // Create the client with default options
18 | client = new StreamrClient({
19 | auth: {
20 | privateKey: PrivateKey
21 | }
22 | })
23 | }
24 |
25 | document.getElementById('subscribe').addEventListener('click', async () => {
26 | if (!client) {
27 | log('Client hasn\'t been initialized. This is likely because you still need to replace the private key.');
28 | return;
29 | }
30 |
31 | // Subscribe to a stream
32 | await client.subscribe({
33 | stream: '7wa7APtlTq6EC5iTCBy6dw',
34 | // Resend the last 10 messages on connect
35 | resend: {
36 | last: 10,
37 | },
38 | }, (message) => {
39 | // Handle the messages in this stream
40 | log(JSON.stringify(message))
41 | })
42 |
43 | // Event binding examples
44 | client.on('connected', () => {
45 | log('A connection has been established!')
46 | })
47 | })
48 |
49 | document.getElementById('publish').addEventListener('click', async () => {
50 | if (!client) {
51 | log('Client hasn\'t been initialized. This is likely because you still need to replace the private key.');
52 | return;
53 | }
54 |
55 | // Here is the event we'll be sending
56 | const msg = {
57 | hello: 'world',
58 | random: Math.random(),
59 | }
60 |
61 | client.getOrCreateStream({
62 | id: `${await client.getAddress()}/webpack-example-data`,
63 | }).then((stream) => setInterval(() => {
64 | // Publish the message to the Stream
65 | client.publish(stream, msg)
66 | .then(() => log(`Sent successfully: ${JSON.stringify(msg)}`))
67 | .catch((err) => console.error(err))
68 | }, 1000))
69 | })
70 |
--------------------------------------------------------------------------------
/Browser/www/web-example-publish.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Publish
9 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/Browser/www/web-example-metamask.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
58 |
59 |
60 |
61 | Connect
62 | Create stream
63 |
64 | Logs
65 |
66 |
67 |
--------------------------------------------------------------------------------
/LightNodeJs/test/Stream.test.js:
--------------------------------------------------------------------------------
1 | const addToStorageNode = require('../src/stream/addToStorageNode.js')
2 | const getPermissions = require('../src/stream/getPermissions.js')
3 | const grantPermission = require('../src/stream/grantPermission.js')
4 | const hasPermission = require('../src/stream/hasPermission.js')
5 | const publish = require('../src/stream/publish.js')
6 | const revokePermission = require('../src/stream/revokePermission.js')
7 |
8 | const expectConsoleLogs = (logs) => {
9 | // only evaluates the first element of the console log, if given comma-separated
10 | for (let i = 0; i < logs.length; i++){
11 | expect(console.log.mock.calls[i][0]).toBe(logs[i])
12 | }
13 | }
14 |
15 | describe('Stream', () => {
16 | beforeEach (() => {
17 | console.log = jest.fn()
18 | })
19 |
20 | it ('should exercise the `addToStorageNode` example', async () => {
21 | const streamId = await addToStorageNode()
22 | expectConsoleLogs([
23 | `Stream ${streamId} created`,
24 | 'Stream added to storage node'
25 | ])
26 | })
27 |
28 | it ('should exercise the `getPermissions` example', async () => {
29 | const {streamId, permissions} = await getPermissions()
30 | expect(permissions.length).toBe(6)
31 | expectConsoleLogs([
32 | `Stream ${streamId} created`,
33 | 'Permissions'
34 | ])
35 | })
36 |
37 | it ('should exercise the `grantPermission` example', async () => {
38 | const streamId = await grantPermission()
39 | expectConsoleLogs([
40 | `Stream ${streamId} created`,
41 | 'Permissions'
42 | ])
43 | })
44 |
45 | it ('should exercise the `hasPermission` example', async () => {
46 | const streamId = await hasPermission()
47 | expectConsoleLogs([
48 | `Stream ${streamId} created`,
49 | 'hasPermission? no',
50 | 'hasPermission? yes'
51 | ])
52 | })
53 |
54 | it ('should exercise the `publish` example', async () => {
55 | const { client, interval} = await publish()
56 | clearInterval(interval)
57 | expectConsoleLogs([
58 | 'Sent successfully: '
59 | ])
60 | await client.destroy()
61 | })
62 |
63 | it ('should exercise the `revokePermission` example', async () => {
64 | const streamId = await revokePermission()
65 | expectConsoleLogs([
66 | 'Permission granted',
67 | 'Permission revoked'
68 | ])
69 | })
70 | })
--------------------------------------------------------------------------------
/BrokerApiNode/README.md:
--------------------------------------------------------------------------------
1 | # Broker APIs
2 | This example demostrates how to use the Streamr Broker API's from NodeJS. Node version 16 is recommended.
3 |
4 | ## Broker & SDKs
5 | - [Examples directory](BrokerApiNode/src/)
6 |
7 | The Broker node ships with interface plugins, which can be used to publish and subscribe to data from applications over off-the-shelf protocols HTTP, Websocket, and MQTT.
8 |
9 | The plugins expose ports and API endpoints which can be used to publish and subscribe to data using the identity of the Broker node.
10 |
11 | ### Global `streamr-broker` setup
12 | ```shell
13 | $ npm install streamr-broker --global
14 | $ streamr-broker-init
15 | # Start the broker
16 | $ streamr-broker ~/.streamr/config/default.json
17 | ```
18 | ### Examples setup
19 | The repository will install `streamr-broker` locally
20 | ```shell
21 | $ npm install
22 | $ npm run broker:start
23 | ```
24 | The [default config](NodeJs/broker-config.json) has the HTTP, WS and MQTT plugins enabled by default to allow for SDK interaction.
25 |
26 | You can also start the broker with the apiKey `0x1c4343df92f5370208232782c373fa691c3543bdf4c40adfd406c87103b18fc2` by running:
27 |
28 | ```
29 | $ npm run broker:start-api-key
30 | ```
31 |
32 | In this setup you'll have to provide one of the registered apiKeys under `src/config-api-key.json` to be able to interact with the broker node.
33 |
34 | ### HTTP Endpoint
35 | One can exercise the [`publish`](BrokerApiNode/src/http-publish.js) using the HTTP plugin on the broker.
36 |
37 |
38 | In order to run this repo's HTTP publish example, execute from your terminal:
39 | ```shell
40 | $ npm run http:publish
41 | ```
42 |
43 | If you are running your broker config with `apiKeys`, you'll need to run:
44 | ```shell
45 | $ npm run http:api-key-publish
46 | ```
47 |
48 | ### WS Endpoint
49 | One can exercise the [`publish`](BrokerApiNode/src/ws-publish.js) and [`subscribe`](BrokerApiNode/src/ws-subscribe.js) using the WebSockets plugin on the broker.
50 |
51 | In order to run the respective examples execute from your terminal:
52 | ```shell
53 | $ npm run ws:subscribe
54 | $ npm run ws:publish
55 | ```
56 |
57 | If you are running your broker config with apiKeys you'll need to run:
58 | ```shell
59 | $ npm run ws:api-key-subscribe
60 | $ npm run ws:api-key-publish
61 | ```
62 |
63 | **Things to remember**
64 | - Any WebSocket client library can be used to interact with the broker
65 | - You must connect to different paths (`/streams/{streamId}/publish` vs `/streams/{streamId}/subscribe`) to interact with the network
66 |
67 | ### MQTT Endpoint
68 | One can exercise the [`publish`](BrokerApiNode/src/mqtt-publish.js) and [`subscribe`](BrokerApiNode/src/mqtt-subscribe.js) using the MQTT plugin on the broker.
69 |
70 | In order to run the respective examples execute from your terminal:
71 | ```shell
72 | $ npm run mqtt:subscribe
73 | $ npm run mqtt:publish
74 | ```
75 |
76 | If you are running your broker config with apiKeys you'll need to run:
77 | ```shell
78 | $ npm run mqtt:api-key-subscribe
79 | $ npm run mqtt:api-key-publish
80 | ```
81 |
82 |
83 | ## Resources
84 | - [Fix permissions when globally installing broker](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)
85 |
86 |
87 |
--------------------------------------------------------------------------------
/LightNodeJs/test/Client.test.js:
--------------------------------------------------------------------------------
1 | const connect = require('../src/connect.js')
2 | const createStream = require('../src/createStream.js')
3 | const getOrCreateStream = require('../src/getOrCreateStream.js')
4 | const getStream = require('../src/getStream.js')
5 | const getSubscriptions = require('../src/getSubscriptions.js')
6 | const publish = require('../src/publish.js')
7 | const subscribe = require('../src/subscribe.js')
8 | const unsubscribe = require('../src/unsubscribe.js')
9 | const unsubscribeAll = require('../src/unsubscribeAll.js')
10 |
11 | const expectConsoleLogs = (logs) => {
12 | // only evaluates the first element of the console log, if given comma-separated
13 | for (let i = 0; i < logs.length; i++){
14 | expect(console.log.mock.calls[i][0]).toBe(logs[i])
15 | }
16 | }
17 |
18 | describe('Client', () => {
19 | beforeEach (() => {
20 | console.log = jest.fn()
21 | })
22 |
23 | it ('should exercise the `connect` example', async () => {
24 | const res = await connect()
25 | expectConsoleLogs([
26 | 'streamr client connected',
27 | 'is client destroyed? no',
28 | 'is client destroyed? yes'
29 | ])
30 | })
31 |
32 | it ('should exercise the `createStream` example', async () => {
33 | const streamId = await createStream()
34 | expectConsoleLogs([
35 | `Stream ${streamId} created`
36 | ])
37 | }).timeout(30 * 1000)
38 |
39 | it ('should exercise the `getOrCreateStream` example', async () => {
40 | const streamId = await getOrCreateStream()
41 | expectConsoleLogs([
42 | `Stream ${streamId} fetched/created`
43 | ])
44 | })
45 |
46 | it ('should exercise the `getStream` example', async () => {
47 | const streamId = await getStream()
48 | expectConsoleLogs([
49 | `Stream ${streamId} created`,
50 | `Stream ${streamId} fetched`
51 | ])
52 | })
53 |
54 | it ('should exercise the `getSubscriptions` example', async () => {
55 | const subscriptions = await getSubscriptions()
56 | expectConsoleLogs([
57 | 'subscriptions'
58 | ])
59 | expect(subscriptions.length).toBe(1)
60 | })
61 |
62 | it ('should exercise the `publish` example', async () => {
63 | const { client, interval} = await publish()
64 | clearInterval(interval)
65 | expectConsoleLogs([
66 | 'Sent successfully: '
67 | ])
68 | await client.destroy()
69 | })
70 |
71 | it ('should exercise the `resend` example', async () => {
72 | // PENDING
73 | })
74 |
75 | it ('should exercise the `subscribe` example', async () => {
76 | const { client, subscription} = await subscribe()
77 | expectConsoleLogs([
78 | 'client created',
79 | 'subscription created'
80 | ])
81 | await client.destroy()
82 | })
83 |
84 | it ('should exercise the `unsubscribe` example', async () => {
85 | const streamId = await unsubscribe()
86 | expectConsoleLogs([
87 | 'Stream fetched:',
88 | `Subscribed to stream ${streamId}`,
89 | `Unsubscribed from stream ${streamId}`
90 | ])
91 | })
92 |
93 | it ('should exercise the `unsubscribeAll` example', async () => {
94 | const streamId = await unsubscribeAll()
95 | expectConsoleLogs([
96 | 'Stream fetched:',
97 | `Subscribed to stream ${streamId}`,
98 | `Unsubscribed from all streams`
99 | ])
100 | })
101 | })
--------------------------------------------------------------------------------
/Browser/www/web-example-subscribe.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
49 |
50 |
51 |
52 |
53 | Real-time telemetrics from trams running in Helsinki, Finland.
54 | Provided by the local public transport authority (HSL) over MQTT protocol.
55 |
59 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/BrokerApiPython/requirements.txt:
--------------------------------------------------------------------------------
1 | certifi==2021.5.30
2 | keyboard==0.13.5
3 | Pillow==8.3.2
4 | pyobjc==7.3
5 | pyobjc-core==7.3
6 | pyobjc-framework-Accessibility==7.3
7 | pyobjc-framework-Accounts==7.3
8 | pyobjc-framework-AddressBook==7.3
9 | pyobjc-framework-AdServices==7.3
10 | pyobjc-framework-AdSupport==7.3
11 | pyobjc-framework-AppleScriptKit==7.3
12 | pyobjc-framework-AppleScriptObjC==7.3
13 | pyobjc-framework-ApplicationServices==7.3
14 | pyobjc-framework-AppTrackingTransparency==7.3
15 | pyobjc-framework-AuthenticationServices==7.3
16 | pyobjc-framework-AutomaticAssessmentConfiguration==7.3
17 | pyobjc-framework-Automator==7.3
18 | pyobjc-framework-AVFoundation==7.3
19 | pyobjc-framework-AVKit==7.3
20 | pyobjc-framework-BusinessChat==7.3
21 | pyobjc-framework-CalendarStore==7.3
22 | pyobjc-framework-CallKit==7.3
23 | pyobjc-framework-CFNetwork==7.3
24 | pyobjc-framework-ClassKit==7.3
25 | pyobjc-framework-CloudKit==7.3
26 | pyobjc-framework-Cocoa==7.3
27 | pyobjc-framework-Collaboration==7.3
28 | pyobjc-framework-ColorSync==7.3
29 | pyobjc-framework-Contacts==7.3
30 | pyobjc-framework-ContactsUI==7.3
31 | pyobjc-framework-CoreAudio==7.3
32 | pyobjc-framework-CoreAudioKit==7.3
33 | pyobjc-framework-CoreBluetooth==7.3
34 | pyobjc-framework-CoreData==7.3
35 | pyobjc-framework-CoreHaptics==7.3
36 | pyobjc-framework-CoreLocation==7.3
37 | pyobjc-framework-CoreMedia==7.3
38 | pyobjc-framework-CoreMediaIO==7.3
39 | pyobjc-framework-CoreMIDI==7.3
40 | pyobjc-framework-CoreML==7.3
41 | pyobjc-framework-CoreMotion==7.3
42 | pyobjc-framework-CoreServices==7.3
43 | pyobjc-framework-CoreSpotlight==7.3
44 | pyobjc-framework-CoreText==7.3
45 | pyobjc-framework-CoreWLAN==7.3
46 | pyobjc-framework-CryptoTokenKit==7.3
47 | pyobjc-framework-DeviceCheck==7.3
48 | pyobjc-framework-DictionaryServices==7.3
49 | pyobjc-framework-DiscRecording==7.3
50 | pyobjc-framework-DiscRecordingUI==7.3
51 | pyobjc-framework-DiskArbitration==7.3
52 | pyobjc-framework-DVDPlayback==7.3
53 | pyobjc-framework-EventKit==7.3
54 | pyobjc-framework-ExceptionHandling==7.3
55 | pyobjc-framework-ExecutionPolicy==7.3
56 | pyobjc-framework-ExternalAccessory==7.3
57 | pyobjc-framework-FileProvider==7.3
58 | pyobjc-framework-FileProviderUI==7.3
59 | pyobjc-framework-FinderSync==7.3
60 | pyobjc-framework-FSEvents==7.3
61 | pyobjc-framework-GameCenter==7.3
62 | pyobjc-framework-GameController==7.3
63 | pyobjc-framework-GameKit==7.3
64 | pyobjc-framework-GameplayKit==7.3
65 | pyobjc-framework-ImageCaptureCore==7.3
66 | pyobjc-framework-IMServicePlugIn==7.3
67 | pyobjc-framework-InputMethodKit==7.3
68 | pyobjc-framework-InstallerPlugins==7.3
69 | pyobjc-framework-InstantMessage==7.3
70 | pyobjc-framework-Intents==7.3
71 | pyobjc-framework-IOSurface==7.3
72 | pyobjc-framework-iTunesLibrary==7.3
73 | pyobjc-framework-KernelManagement==7.3
74 | pyobjc-framework-LatentSemanticMapping==7.3
75 | pyobjc-framework-LaunchServices==7.3
76 | pyobjc-framework-libdispatch==7.3
77 | pyobjc-framework-LinkPresentation==7.3
78 | pyobjc-framework-LocalAuthentication==7.3
79 | pyobjc-framework-MapKit==7.3
80 | pyobjc-framework-MediaAccessibility==7.3
81 | pyobjc-framework-MediaLibrary==7.3
82 | pyobjc-framework-MediaPlayer==7.3
83 | pyobjc-framework-MediaToolbox==7.3
84 | pyobjc-framework-Metal==7.3
85 | pyobjc-framework-MetalKit==7.3
86 | pyobjc-framework-MetalPerformanceShaders==7.3
87 | pyobjc-framework-MetalPerformanceShadersGraph==7.3
88 | pyobjc-framework-MLCompute==7.3
89 | pyobjc-framework-ModelIO==7.3
90 | pyobjc-framework-MultipeerConnectivity==7.3
91 | pyobjc-framework-NaturalLanguage==7.3
92 | pyobjc-framework-NetFS==7.3
93 | pyobjc-framework-Network==7.3
94 | pyobjc-framework-NetworkExtension==7.3
95 | pyobjc-framework-NotificationCenter==7.3
96 | pyobjc-framework-OpenDirectory==7.3
97 | pyobjc-framework-OSAKit==7.3
98 | pyobjc-framework-OSLog==7.3
99 | pyobjc-framework-PassKit==7.3
100 | pyobjc-framework-PencilKit==7.3
101 | pyobjc-framework-Photos==7.3
102 | pyobjc-framework-PhotosUI==7.3
103 | pyobjc-framework-PreferencePanes==7.3
104 | pyobjc-framework-PushKit==7.3
105 | pyobjc-framework-Quartz==7.3
106 | pyobjc-framework-QuickLookThumbnailing==7.3
107 | pyobjc-framework-ReplayKit==7.3
108 | pyobjc-framework-SafariServices==7.3
109 | pyobjc-framework-SceneKit==7.3
110 | pyobjc-framework-ScreenSaver==7.3
111 | pyobjc-framework-ScreenTime==7.3
112 | pyobjc-framework-ScriptingBridge==7.3
113 | pyobjc-framework-SearchKit==7.3
114 | pyobjc-framework-Security==7.3
115 | pyobjc-framework-SecurityFoundation==7.3
116 | pyobjc-framework-SecurityInterface==7.3
117 | pyobjc-framework-ServiceManagement==7.3
118 | pyobjc-framework-Social==7.3
119 | pyobjc-framework-SoundAnalysis==7.3
120 | pyobjc-framework-Speech==7.3
121 | pyobjc-framework-SpriteKit==7.3
122 | pyobjc-framework-StoreKit==7.3
123 | pyobjc-framework-SyncServices==7.3
124 | pyobjc-framework-SystemConfiguration==7.3
125 | pyobjc-framework-SystemExtensions==7.3
126 | pyobjc-framework-UniformTypeIdentifiers==7.3
127 | pyobjc-framework-UserNotifications==7.3
128 | pyobjc-framework-UserNotificationsUI==7.3
129 | pyobjc-framework-VideoSubscriberAccount==7.3
130 | pyobjc-framework-VideoToolbox==7.3
131 | pyobjc-framework-Virtualization==7.3
132 | pyobjc-framework-Vision==7.3
133 | pyobjc-framework-WebKit==7.3
134 |
--------------------------------------------------------------------------------
/Tutorials/mqtt/README.md:
--------------------------------------------------------------------------------
1 | # Bridging data into the Streamr Network using the Broker node MQTT interface
2 | In this tutorial you will publish data into the Streamr Network using the MQTT interface of a Streamr Network Broker node.
3 |
4 | ## 1. Setup your Broker node.
5 | This tutorial is applicable for MacOS/Linux environments. Windows environments may require minor adjustments (file locations, etc). For more in depth information on installing a Broker node, see the [installing a Broker node docs](https://streamr.network/docs/streamr-network/installing-broker-node).
6 |
7 | Prerequisites:
8 | - NPM v8
9 | - NodeJS 16.13.x
10 |
11 | ### Install `streamr-broker` globally
12 | ```shell
13 | $ npm i -g streamr-broker
14 | ```
15 |
16 | This tutorial uses Broker node version `31.0.1` but always use the latest stable version when possible.
17 |
18 | ### Initial Broker node setup
19 | Before the Broker node can be started its configuration files need to be created using the following command:
20 | ```shell
21 | $ streamr-broker-init
22 | ```
23 | After creating or importing your private key you will have to enable the `mqtt-plugin` and assign a port to it (default is 1883)
24 |
25 | Once the script is done you can view your generated configuration file with:
26 | ```shell
27 | $ cat ~/.streamr/config/default.json
28 | ```
29 |
30 | ### Start the Broker node
31 | Start the broker by running:
32 | ```shell
33 | $ streamr-broker
34 | ```
35 |
36 | To include more verbose logging you can run the Broker with these additional flags:
37 | ```shell
38 | $ LOG_LEVEL=trace DEBUG=Streamr* streamr-broker
39 | ```
40 |
41 | ## 2. Create a stream and update it's access control
42 | In this step the Broker node is given permission to publish data points to the stream.
43 |
44 | In order to create a stream you will need an Ethereum address with a small amount of `MATIC` to pay for gas during stream creation and permission assignment. `MATIC` is the native token of the Polygon blockchain.
45 |
46 | This tutorial uses Streamr Client version `6.0.4` but always use the latest stable version when possible.
47 |
48 | ### Initialize the Streamr Client
49 | Inside a NodeJS script, instantiate a `StreamrClient` instance called `streamr`, with the funded Ethereum account (private key) from the previous step:
50 | ```javascript
51 | const streamr = new StreamrClient({
52 | auth: {
53 | privateKey: PRIVATE_KEY,
54 | }
55 | })
56 | ```
57 |
58 | ### Create the stream
59 | With our `streamr` instance we can now create a stream:
60 | ```javascript
61 | const stream = await streamr.createStream({
62 | id: '/sensor/firehose',
63 | })
64 | ```
65 |
66 | The full stream ID contains the public key of the Ethereum identity (public key) that instantiated the `StreamrClient` instance. I.e. `0x123/sensor/firehose`.
67 |
68 | You may also use Streamr's [UI](https://streamr.network/core) to create the stream and edit its access control. For more information on stream creation, see our docs secion on [creating streams](https://streamr.network/docs/streams/creating-streams).
69 |
70 | ### Assign stream permissions
71 | This step will also consume a small amount of `MATIC` tokens.
72 |
73 | We will be granting the Broker node `PUBLISH` and `SUBSCRIBE` permissions on the stream we just created.
74 |
75 | We will need to provide the `StreamId`, as well as the `BrokerNodeAddress`. The `BrokerNodeAddress` (public key) is displayed when the Broker node is started:
76 | ```javascript
77 | await streamr.setPermissions({
78 | streamId: StreamId,
79 | assignments: [
80 | {
81 | user: BrokerNodeAddress,
82 | permissions: [
83 | StreamPermission.PUBLISH,
84 | StreamPermission.SUBSCRIBE
85 | ]
86 | }
87 | ]
88 | })
89 | ```
90 |
91 | Alternatively, you can easily create a stream and assign its permissions with the [Create stream and assign permissions script](./scripts/01-CreateStreamAndAssignPermissions.js). You will need to provide a value for `PrivateKey` that has `MATIC` balance, as well as the generated address of your Broker node, `BrokerNodeAddress`:
92 |
93 | ```javascript
94 | const PrivateKey = '...'
95 | ...
96 | const BrokerNodeAddress = '0x...'
97 | ```
98 |
99 | After setting these values you can run the script with:
100 | ```shell
101 | $ node scripts/01-CreateStreamAndAssignPermissions.js
102 | ```
103 |
104 | Be sure to not expose your private key to anyone or upload it to any public GitHub repository by accident!
105 |
106 | ## 3. Configure your app or device to publish to the Streamr Broker node's MQTT interface
107 | Note, in order to publish data to our newly created stream, our Broker node will need to be running.
108 |
109 | ### MQTT interface authentication
110 | Your app or device publishing to the MQTT interface will need to provide the `ApiKey` from the Broker node's configuration file, which you can find here:
111 |
112 | ```shell
113 | $ cat ~/.streamr/config/default.json
114 | ```
115 | ```json
116 | {
117 | ...
118 | "apiAuthentication": {
119 | "keys": [
120 | "ImTheKeyYouAreLookingFor"
121 | ]
122 | }
123 | }
124 | ```
125 |
126 | More details about using the plugin interface can be found in the [Connecting applications docs](https://streamr.network/docs/streamr-network/connecting-applications) and more in depth information about the plugin interface can be found in the [Broker plugin docs](https://github.com/streamr-dev/network-monorepo/blob/main/packages/broker/plugins.md).
127 |
128 | If you're connecting to the MQTT interface over the open internet, please remember to make sure the port is open.
129 |
130 | ### Connecting to the MQTT interface
131 | You will need to provide the URL with the MQTT port (default is 1883), as well as an empty `username` field and the `ApiKey` as the `password`.
132 |
133 | ```javascript
134 | // Node.js example
135 |
136 | const mqttClient = await mqtt.connectAsync(
137 | 'mqtt://localhost:1883',
138 | {
139 | username: '',
140 | password: ApiKey,
141 | }
142 | )
143 | ```
144 |
145 | Or you may need authenticate with a URL, for example `mqtt://"":ApiKey@1.2.3.4:1883`. Some MQTT libraries may have issue with an empty username, to get around this you can provide "x" as the username.
146 |
147 | ### Publishing data
148 | Once connected, the MQTT client can begin publishing data points by providing a `StreamId` as the first parameter and the JSON payload as the second parameter.
149 |
150 | ```javascript
151 | // Node.js example
152 |
153 | await mqttClient.publish(
154 | StreamId,
155 | JSON.stringify({ foo: bar })
156 | )
157 |
158 | ```
159 |
160 | Note, at the time of writing, the Broker node will reject any non-JSON payload - so make sure your data is in JSON format! You can find a NodeJS example using `async-mqtt` in the [MQTT publisher script](./scripts/02-MqttPublisher.js).
161 |
162 | Your data points are now being published into the Streamr Network, via your Broker node, inside the stream you've created.
163 |
164 | ## 4. Subscribe to your stream
165 | The last remaining step is to connect to the Streamr Network and consume/subscribe to your data!
166 |
167 | ### Subscribe using the Streamr UI
168 | You can see the published messages on your streams by using [Streamr's UI](https://streamr.network/core), logging in with Metamask with your Broker's private key (you will need to "Import account by private key"), finding your stream, and observing the live stream data preview.
169 |
170 | ### Subscribe using the Streamr CLI tool
171 | Alternativecly, you can use [Streamr's CLI tool](
172 | https://github.com/streamr-dev/network-monorepo/tree/main/packages/cli-tools) to subscribe to the created streams and see its incoming messages:
173 |
174 | ```shell
175 | $ npm install -g @streamr/cli-tools
176 | $ streamr stream subscribe 0x.../sensor/firehose --private-key YOUR_PRIVATE_KEY
177 | ```
178 |
179 | ### Subscribe using a Broker node interface
180 | Just like you used the Broker node's MQTT interface to publish data into the network, you can also pull data out of the Network via any Broker nodes interface just as well. Just make sure that the Broker node has `SUBSCRIBE` permission to the stream you are interested in.
181 |
182 | You will need to authenticate your client using your `ApiKey`.
183 |
184 | Once connected, you can listen for the `message` callback on the MQTT client. The first parameter will be the `StreamId` and the second parameter will contain the message JSON payload:
185 |
186 | ```javascript
187 | // NodeJS example
188 |
189 | mqttClient.subscribe(StreamId)
190 | ...
191 | mqttClient.on('connect', () => {
192 | mqttClient.on('message', (streamId, rawData) => {
193 | ...
194 | })
195 | })
196 | ```
197 |
198 | You can find this example [MQTT subscriber script](./scripts/03-MqttSubscriber.js) in this repo.
199 |
200 | ## 5. All done 🎉
201 | Congratulations! You accomplished:
202 | - Running a node in the Streamr Network,
203 | - Created a stream and edited its access control on the on-chain stream registry,
204 | - Published data to the Streamr Network using the MQTT interface of your running Broker node,
205 | - Subscribed to your flowing data.
206 |
207 | If you had any problems along the way, please drop a message to the core team on the #dev channel of our [Discord](https://discord.gg/gZAm8P7hK8).
208 |
--------------------------------------------------------------------------------