├── 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 | 6 | 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 ![following line](https://github.com/streamr-dev/examples/blob/c2c736e25911705c0f549637a73654168bb2ec10/Webpack/src/index.js#L10) 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 | Streamr 4 | 5 |

6 | 7 |

8 | Streamr usage examples 9 |

10 | 11 | [![Discord Chat](https://img.shields.io/discord/801574432350928907.svg?label=Discord&logo=Discord&colorB=7289da)](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 ![following line](https://github.com/streamr-dev/examples/blob/c2c736e25911705c0f549637a73654168bb2ec10/Web/web-example-produce.html#L23) with your private key. 17 | - Replace the ![following line](https://github.com/streamr-dev/examples/blob/c2c736e25911705c0f549637a73654168bb2ec10/Web/web-example-publish.html#L20) 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 | 9 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Browser/www/web-example-metamask.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 58 | 59 | 60 | 61 | 62 | 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 |
56 |
57 |
58 |
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 | --------------------------------------------------------------------------------