npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-red-contrib-opentimestamps

v0.0.7

Published

Node-RED implementation of OpenTimestamps.

Downloads

103

Readme

node-red-contrib-opentimestamps

A collection of Node-RED nodes use the OpenTimestamps services.

What you mean with opentimestamps?

A timestamping proof standard

OpenTimestamps aims to be a standard format for blockchain timestamping. The format is flexible enough to be vendor and blockchain independent.

OpenTimestamps is a standard for obtain a service with Trustless Timestamps or in other words timestamps secured by the blockchain.

Install

Use npm to command to install this package locally in the Node-RED modules directory

npm install node-red-contrib-opentimestamps

or install in it globally with the command

npm install node-red-contrib-opentimestamps -g

Nodes included in the package

OTS_Stamp create an opentimestamps proof based on the data on buffer msg.fileArray and save the receipt on the buffer msg.otsArray

OTS_Info convert the opentimestamps receipt (taken from msg.otsArray ) in a readable format available on the msg.payload (as a string)

OTS_Upgrade upgrade the receipt available in the buffer msg.otsArray (overwrite the previous content)

OTS_Verify based on the two buffer msg.fileArray and msg.otsArray calculate if a message is valid or not and answer with the result in a readable format on msg.payload

Usage example

A Simple usage of the plugin in Node-RED can be a message broker that work in the following way:

  • receive a message from an input queue,
  • request the timestamp for the payload and save the receipt from the opentimestamps server,
  • create a new message with a JSON with the data of the oringinal payload and the receipt from opentimestamp server,
  • send the message on the output queue.

MQTT timestamping broker

mqtt_flow

The first implementation was a broker for timestamp messages flowing in a MQTT server, the flow of the broker is the part in the red box.

[
    {
        "id": "86aec060.69b3d",
        "type": "inject",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "topic": "",
        "payload": "bla bla",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "x": 90,
        "y": 60,
        "wires": [
            [
                "10ea2927.96f247"
            ]
        ]
    },
    {
        "id": "3a768aaa.e483d6",
        "type": "OTS_Stamp",
        "z": "3c8a5604.39f8ba",
        "name": "OTS_Stamp",
        "x": 430,
        "y": 260,
        "wires": [
            [
                "2996139.6165bec",
                "208b34b.419b8cc"
            ]
        ]
    },
    {
        "id": "a8e88100.e5485",
        "type": "function",
        "z": "3c8a5604.39f8ba",
        "name": "Convert",
        "func": "msg.fileArray = new Buffer(msg.payload);\nmsg.payload = null;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 240,
        "y": 260,
        "wires": [
            [
                "3a768aaa.e483d6"
            ]
        ]
    },
    {
        "id": "2996139.6165bec",
        "type": "OTS_Info",
        "z": "3c8a5604.39f8ba",
        "name": "OTS_Info",
        "x": 640,
        "y": 300,
        "wires": [
            [
                "5e5825f7.d0b5ec"
            ]
        ]
    },
    {
        "id": "5e5825f7.d0b5ec",
        "type": "debug",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "payload",
        "x": 850,
        "y": 300,
        "wires": []
    },
    {
        "id": "208b34b.419b8cc",
        "type": "function",
        "z": "3c8a5604.39f8ba",
        "name": "Convert",
        "func": "msg.payload = {}\nmsg.payload.data = msg.fileArray;\nmsg.payload.ots = msg.otsArray;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 640,
        "y": 220,
        "wires": [
            [
                "911bbcd8.9ea6"
            ]
        ]
    },
    {
        "id": "630c703c.e22b5",
        "type": "mqtt in",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "topic": "ingress_timestamped",
        "qos": "2",
        "broker": "b2e0c3ab.d24db",
        "x": 260,
        "y": 480,
        "wires": [
            [
                "8a4a0f7e.c5b8d"
            ]
        ]
    },
    {
        "id": "10ea2927.96f247",
        "type": "mqtt out",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "topic": "ingress",
        "qos": "",
        "retain": "",
        "broker": "b2e0c3ab.d24db",
        "x": 240,
        "y": 60,
        "wires": []
    },
    {
        "id": "f6c25dc9.0707a",
        "type": "mqtt in",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "topic": "ingress",
        "qos": "2",
        "broker": "b2e0c3ab.d24db",
        "x": 90,
        "y": 260,
        "wires": [
            [
                "a8e88100.e5485"
            ]
        ]
    },
    {
        "id": "911bbcd8.9ea6",
        "type": "mqtt out",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "topic": "ingress_timestamped",
        "qos": "",
        "retain": "",
        "broker": "b2e0c3ab.d24db",
        "x": 880,
        "y": 220,
        "wires": []
    },
    {
        "id": "1da4a149.b2b18f",
        "type": "debug",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "true",
        "x": 630,
        "y": 440,
        "wires": []
    },
    {
        "id": "912c107d.aa1e7",
        "type": "change",
        "z": "3c8a5604.39f8ba",
        "name": "Get data",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.data",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 640,
        "y": 480,
        "wires": [
            [
                "c5dc3887.176e88"
            ]
        ]
    },
    {
        "id": "1f918b60.31f315",
        "type": "change",
        "z": "3c8a5604.39f8ba",
        "name": "Get OTS",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.ots",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 640,
        "y": 520,
        "wires": [
            [
                "1a0710d9.4f655f"
            ]
        ]
    },
    {
        "id": "c5dc3887.176e88",
        "type": "function",
        "z": "3c8a5604.39f8ba",
        "name": "Set filename",
        "func": "msg.filename = \"/opt/opentimestamp/dump-mqtt/\" + msg._msgid + \".data\"\nmsg.payload = new Buffer(msg.payload);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 810,
        "y": 480,
        "wires": [
            [
                "7c6d470.33266b8"
            ]
        ]
    },
    {
        "id": "1a0710d9.4f655f",
        "type": "function",
        "z": "3c8a5604.39f8ba",
        "name": "Set filename",
        "func": "msg.filename = \"/opt/opentimestamp/dump-mqtt/\" + msg._msgid + \".ots\"\nmsg.payload = new Buffer(msg.payload);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 810,
        "y": 520,
        "wires": [
            [
                "9b51894d.fb96c8"
            ]
        ]
    },
    {
        "id": "7c6d470.33266b8",
        "type": "file",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "filename": "",
        "appendNewline": false,
        "createDir": false,
        "overwriteFile": "true",
        "x": 970,
        "y": 480,
        "wires": []
    },
    {
        "id": "9b51894d.fb96c8",
        "type": "file",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "filename": "",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "false",
        "x": 970,
        "y": 520,
        "wires": []
    },
    {
        "id": "8a4a0f7e.c5b8d",
        "type": "json",
        "z": "3c8a5604.39f8ba",
        "name": "",
        "x": 450,
        "y": 480,
        "wires": [
            [
                "1da4a149.b2b18f",
                "912c107d.aa1e7",
                "1f918b60.31f315"
            ]
        ]
    },
    {
        "id": "b2e0c3ab.d24db",
        "type": "mqtt-broker",
        "z": "",
        "broker": "test.mosquitto.org",
        "port": "1883",
        "clientid": "",
        "usetls": false,
        "compatmode": true,
        "keepalive": "60",
        "cleansession": true,
        "willTopic": "",
        "willQos": "0",
        "willPayload": "",
        "birthTopic": "",
        "birthQos": "0",
        "birthPayload": ""
    }
]

AMQP timestamping broker

mqtt_flow

The same flow can be implemented using AMQP instead of MQTT with a similar flow.

[
    {
        "id": "c96a6450.746888",
        "type": "inject",
        "z": "4392d5db.3b662c",
        "name": "",
        "topic": "",
        "payload": "bla bla",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "x": 90,
        "y": 60,
        "wires": [
            [
                "d643a206.ef485"
            ]
        ]
    },
    {
        "id": "8d6c59c8.a0e228",
        "type": "debug",
        "z": "4392d5db.3b662c",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "true",
        "x": 590,
        "y": 420,
        "wires": []
    },
    {
        "id": "58687119.21835",
        "type": "amqp in",
        "z": "4392d5db.3b662c",
        "name": "",
        "topic": "",
        "iotype": "1",
        "ioname": "ingress_timestamped",
        "server": "22c8fc1b.732854",
        "x": 360,
        "y": 460,
        "wires": [
            [
                "8d6c59c8.a0e228",
                "1fb75e0f.09efa2",
                "a9e5fe7f.6b618"
            ]
        ]
    },
    {
        "id": "d643a206.ef485",
        "type": "amqp out",
        "z": "4392d5db.3b662c",
        "name": "",
        "routingkey": "",
        "iotype": "1",
        "ioname": "ingress",
        "server": "22c8fc1b.732854",
        "x": 220,
        "y": 60,
        "wires": []
    },
    {
        "id": "66a83517.6b462c",
        "type": "amqp in",
        "z": "4392d5db.3b662c",
        "name": "",
        "topic": "",
        "iotype": "1",
        "ioname": "ingress",
        "server": "22c8fc1b.732854",
        "x": 90,
        "y": 220,
        "wires": [
            [
                "e5429fd6.1f08e"
            ]
        ]
    },
    {
        "id": "7874c67.2902b38",
        "type": "OTS_Stamp",
        "z": "4392d5db.3b662c",
        "name": "OTS_Stamp",
        "x": 430,
        "y": 220,
        "wires": [
            [
                "7468042d.a8bcdc",
                "2421d40d.cc059c"
            ]
        ]
    },
    {
        "id": "e5429fd6.1f08e",
        "type": "function",
        "z": "4392d5db.3b662c",
        "name": "Convert",
        "func": "msg.fileArray = new Buffer(msg.payload);\nmsg.payload = null;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 240,
        "y": 220,
        "wires": [
            [
                "7874c67.2902b38"
            ]
        ]
    },
    {
        "id": "7468042d.a8bcdc",
        "type": "OTS_Info",
        "z": "4392d5db.3b662c",
        "name": "OTS_Info",
        "x": 640,
        "y": 260,
        "wires": [
            [
                "54b36dc9.c367a4"
            ]
        ]
    },
    {
        "id": "54b36dc9.c367a4",
        "type": "debug",
        "z": "4392d5db.3b662c",
        "name": "",
        "active": true,
        "console": "false",
        "complete": "payload",
        "x": 850,
        "y": 260,
        "wires": []
    },
    {
        "id": "2421d40d.cc059c",
        "type": "function",
        "z": "4392d5db.3b662c",
        "name": "Convert",
        "func": "msg.payload = {}\nmsg.payload.data = msg.fileArray;\nmsg.payload.ots = msg.otsArray;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 640,
        "y": 180,
        "wires": [
            [
                "d0f7a135.d2704"
            ]
        ]
    },
    {
        "id": "d0f7a135.d2704",
        "type": "amqp out",
        "z": "4392d5db.3b662c",
        "name": "",
        "routingkey": "",
        "iotype": "1",
        "ioname": "ingress_timestamped",
        "server": "22c8fc1b.732854",
        "x": 880,
        "y": 180,
        "wires": []
    },
    {
        "id": "1fb75e0f.09efa2",
        "type": "change",
        "z": "4392d5db.3b662c",
        "name": "Get data",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.data",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 600,
        "y": 460,
        "wires": [
            [
                "48d33270.bb3f0c"
            ]
        ]
    },
    {
        "id": "a9e5fe7f.6b618",
        "type": "change",
        "z": "4392d5db.3b662c",
        "name": "Get OTS",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "payload.ots",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 600,
        "y": 500,
        "wires": [
            [
                "9b07c36e.453f1"
            ]
        ]
    },
    {
        "id": "48d33270.bb3f0c",
        "type": "function",
        "z": "4392d5db.3b662c",
        "name": "Set filename",
        "func": "msg.filename = \"/opt/opentimestamp/dump-amqp/\" + msg._msgid + \".data\"\nmsg.payload = new Buffer(msg.payload);\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 770,
        "y": 460,
        "wires": [
            [
                "b4cdc2a6.e6399"
            ]
        ]
    },
    {
        "id": "9b07c36e.453f1",
        "type": "function",
        "z": "4392d5db.3b662c",
        "name": "Set filename",
        "func": "msg.filename = \"/opt/opentimestamp/dump-amqp/\" + msg._msgid + \".ots\"\nmsg.payload = new Buffer(msg.payload);\nreturn msg",
        "outputs": 1,
        "noerr": 0,
        "x": 770,
        "y": 500,
        "wires": [
            [
                "c56635e0.1f9568"
            ]
        ]
    },
    {
        "id": "b4cdc2a6.e6399",
        "type": "file",
        "z": "4392d5db.3b662c",
        "name": "",
        "filename": "",
        "appendNewline": false,
        "createDir": false,
        "overwriteFile": "true",
        "x": 930,
        "y": 460,
        "wires": []
    },
    {
        "id": "c56635e0.1f9568",
        "type": "file",
        "z": "4392d5db.3b662c",
        "name": "",
        "filename": "",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "false",
        "x": 930,
        "y": 500,
        "wires": []
    },
    {
        "id": "22c8fc1b.732854",
        "type": "amqp-server",
        "z": "",
        "host": "mqtt-broker",
        "port": "5672",
        "vhost": "",
        "keepalive": "30",
        "usetls": false,
        "verifyservercert": true,
        "usetopology": false,
        "topology": "{\n\t\"exchanges\": [\n\t\t{\"name\": \"exchange1\", \"type\": \"direct\", \"options\": {\"durable\": false}},\n\t\t{\"name\": \"exchange2\"}\n\t],\n\t\"queues\": [\n\t\t{\"name\": \"queue1\", \"options\": {\"messageTtl\": 60000}},\n\t\t{\"name\": \"queue2\"}\n\t],\n\t\"bindings\": [\n\t\t{\"source\": \"exchange1\", \"queue\": \"queue1\", \"pattern\": \"debug\", \"args\": {}},\n\t\t{\"source\": \"exchange1\", \"exchange\": \"exchange2\", \"pattern\": \"error\"},\n\t\t{\"source\": \"exchange2\", \"queue\": \"queue2\"}\n\t]\n}"
    }
]

History

Video of the Hackathon available on YouTube DANGER! It's in Italian! :(

Authors

  • Valerio Vaccaro (https://github.com/valerio-vaccaro)

Credits

Node-RED has been made possible by the hard work of Nick O'Leary @knolleary and Dave Conway-Jones @ceejay at IBM Emerging Technology. Much thanks to them and other supporters for advancing this platform. These node use the javascript-opentimestamps library and the opentimestamps public server! Thanks a lot to make it free and open.

This module is developed by Valerio Vaccaro (http://www.valeriovaccaro.it).