{"id":26313906,"url":"https://github.com/opentimestamps/javascript-opentimestamps","last_synced_at":"2025-04-05T15:10:15.333Z","repository":{"id":45332105,"uuid":"81702539","full_name":"opentimestamps/javascript-opentimestamps","owner":"opentimestamps","description":null,"archived":false,"fork":false,"pushed_at":"2023-03-12T16:57:20.000Z","size":1690,"stargazers_count":133,"open_issues_count":17,"forks_count":50,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-29T14:07:13.588Z","etag":null,"topics":["bitcoin","cryptography","javascript","opentimestamps"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opentimestamps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-12T04:23:32.000Z","updated_at":"2025-03-29T02:04:21.000Z","dependencies_parsed_at":"2024-06-18T19:58:16.382Z","dependency_job_id":"a7e060fc-c3ba-478d-a16f-8dac91e9826a","html_url":"https://github.com/opentimestamps/javascript-opentimestamps","commit_stats":{"total_commits":482,"total_committers":25,"mean_commits":19.28,"dds":0.5352697095435685,"last_synced_commit":"c07ba8be0dae4e8721a84f32820abf7b2547a6ce"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentimestamps%2Fjavascript-opentimestamps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentimestamps%2Fjavascript-opentimestamps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentimestamps%2Fjavascript-opentimestamps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentimestamps%2Fjavascript-opentimestamps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opentimestamps","download_url":"https://codeload.github.com/opentimestamps/javascript-opentimestamps/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247353749,"owners_count":20925329,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","cryptography","javascript","opentimestamps"],"created_at":"2025-03-15T11:17:21.038Z","updated_at":"2025-04-05T15:10:15.278Z","avatar_url":"https://github.com/opentimestamps.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# javascript-opentimestamps\n\n[![OpenTimestamps logo][2]][1]\n\n[1]: https://opentimestamps.org\n[2]: https://raw.githubusercontent.com/opentimestamps/logo/master/white-bg/website-horizontal-350x75.png (OpenTimestamps logo)\n\n\n[![Build Status](https://travis-ci.org/opentimestamps/javascript-opentimestamps.svg?branch=master)](https://travis-ci.org/opentimestamps/javascript-opentimestamps)\n\n[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n\n\nThis repository hosts the javascript implementation of OpenTimestamps.\n\nIt is based on the python implementation at [Opentimestamps-Python](https://github.com/opentimestamps/python-opentimestamps) and [Opentimestamps-Client](https://github.com/opentimestamps/opentimestamps-client)\n\nIt has been developed as node modules for being used within Node environments along with Node Package Manager.\n\u003e You can also use it in the browser, see the **Installation** section.\n\n[Jsdoc](https://opentimestamps.org/docs/javascript-opentimestamps/) available\n\n## Installation\n\n#### Node\n\n```shell\n$ npm install -g opentimestamps\n```\n\n**Note** up to version `0.4.5` the name of the lib was `javascript-opentimestamps`, from version `0.4.6` on npm is just `opentimestamps`.\n\n#### Browser\n\n##### Get the \"binaries\"\n\nTake the [js](https://opentimestamps.org/assets/javascripts/vendor/opentimestamps.min.js) used by opentimestamps.org \n\n##### Build from source\n\nFrom this repo, install the dev library\n\n```\nnpm install --dev\n```\n\nthen run the gulp process\n\n```\nnpx gulp\n```\n\ninclude the result `/dist/opentimestamps.min.js` in your page\n\n```html\n\u003cscript src=\"opentimestamps.min.js\"\u003e\u003c/script\u003e\n```\n\n\n## Compatibility\n\n#### Node\n\n\u003e This library is tested on CI against version 6.0, 6.1 and 7. See [__Travis build__](https://travis-ci.org/opentimestamps/javascript-opentimestamps.svg?branch=master) \n\nDownload: [__NodeJS__](https://nodejs.org/en/download/)\n\n#### Browser\n\n\u003e The lib is compatible with ECMAScript6(ES6) and ECMAScript5(ES5).\n\nBrowser compatibility:\n\n* [__Chrome__](https://www.google.com/chrome/browser/desktop/index.html) version \u003e= 40\n* [__Chromium__](https://www.chromium.org/getting-involved/download-chromium) version \u003e= 40\n* [__Firefox__](https://www.mozilla.org/en-US/firefox/new/) version \u003e= 40\n* [__Internet Explorer__](https://www.microsoft.com/en-us/download/internet-explorer.aspx) version \u003e= 9\n* [__Safari__](https://support.apple.com/downloads/safari) version \u003e= 8\n\n## Command Line\n\nThe following example requires you installed globally the javascript-opentimestamps library, if you want to test locally just prepend `node` to the command, like `node ots-cli.js --help`\n\n#### Stamp\n\nCreate timestamp `README.md.ots` from this `README.md` with the aid of a remote calendar.\n\n```shell\n$ ots-cli.js stamp README.md\nSubmitting to remote calendar https://alice.btc.calendar.opentimestamps.org\nSubmitting to remote calendar https://bob.btc.calendar.opentimestamps.org\nSubmitting to remote calendar https://finney.calendar.eternitywall.com\nThe timestamp proof 'README.md.ots' has been created!\n```\n\nIf you already have the hash of some file, you don't need to rehash it:\n\n```shell\n$ ots-cli.js stamp -d 05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9\nSubmitting to remote calendar https://alice.btc.calendar.opentimestamps.org\nSubmitting to remote calendar https://bob.btc.calendar.opentimestamps.org\nSubmitting to remote calendar https://finney.calendar.eternitywall.com\nThe timestamp proof '05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9.ots' has been created!\n```\nNote that verify implicity requires the file must be called like the .ots receipt but without the ots, if you timestamp hashes and want to verify you need to rename files accordingly.\n\nThe default hash used `sha256` but you can also specify other hashes like `sha1` or `ripemd` (eg `ots-cli.js stamp -d 4f8d8389200583977943be86f0f74a964a670405 -a sha1`). Note that partially broken hash function like `sha1` is ok for timestamping purpose because they are [still resistant](https://petertodd.org/2017/sha1-and-opentimestamps-proofs) to preimage attacks (their use is discouraged anyway).\n\n\nThe stamp command supports multiple files or hashes as arguments.\n\n```shell\n$ ots-cli.js stamp README.md ots-cli.js\nSubmitting to remote calendar https://alice.btc.calendar.opentimestamps.org\nSubmitting to remote calendar https://bob.btc.calendar.opentimestamps.org\nSubmitting to remote calendar https://finney.calendar.eternitywall.com\nThe timestamp proof 'ots-cli.js.ots' has been created!\nThe timestamp proof 'README.md.ots' has been created!\n```\n\n#### Info\n\nShow information on a timestamp.\n\n```shell\n$ ots-cli.js info examples/incomplete.txt.ots\nFile sha256 hash: 05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9\nTimestamp:\nappend e754bf93806a7ebaa680ef7bd0114bf4\nsha256\nappend b573e8850cfd9e63d1f043fbb6fc250e\nsha256\nprepend 57cfa5c4\nappend 6fb1ac8d4e4eb0e7\nverify PendingAttestation('https://alice.btc.calendar.opentimestamps.org')\n```\n\nYou can have verbose output which clarifies operations, arguments, results and also contains comments showing the involved transaction id and calculated merkle tree root.\n\n```shell\n$ node ots-cli.js info -v examples/hello-world.txt.ots \nFile sha256 hash: 03ba204e50d126e4674c005e04d82e84c21366780af1f43bd54a37816b6ab340\nTimestamp:\nripemd160 == 1df8859e60bc679503d16dcb870e6ce91a57e9df\nprepend 0100000001e482f9d32ecc3ba657b69d898010857b54457a90497982ff56f97c4ec58e6f98010000006b483045022100b253add1d1cf90844338a475a04ff13fc9e7bd242b07762dea07f5608b2de367022000b268ca9c3342b3769cdd062891317cdcef87aac310b6855e9d93898ebbe8ec0121020d8e4d107d2b339b0050efdd4b4a09245aa056048f125396374ea6a2ab0709c6ffffffff026533e605000000001976a9140bf057d40fbba6744862515f5b55a2310de5772f88aca0860100000000001976a914 == 0100000001e482f9d32ecc3ba657b69d898010857b54457a90497982ff56f97c4ec58e6f98010000006b483045022100b253add1d1cf90844338a475a04ff13fc9e7bd242b07762dea07f5608b2de367022000b268ca9c3342b3769cdd062891317cdcef87aac310b6855e9d93898ebbe8ec0121020d8e4d107d2b339b0050efdd4b4a09245aa056048f125396374ea6a2ab0709c6ffffffff026533e605000000001976a9140bf057d40fbba6744862515f5b55a2310de5772f88aca0860100000000001976a9141df8859e60bc679503d16dcb870e6ce91a57e9df\nappend 88ac00000000 == 0100000001e482f9d32ecc3ba657b69d898010857b54457a90497982ff56f97c4ec58e6f98010000006b483045022100b253add1d1cf90844338a475a04ff13fc9e7bd242b07762dea07f5608b2de367022000b268ca9c3342b3769cdd062891317cdcef87aac310b6855e9d93898ebbe8ec0121020d8e4d107d2b339b0050efdd4b4a09245aa056048f125396374ea6a2ab0709c6ffffffff026533e605000000001976a9140bf057d40fbba6744862515f5b55a2310de5772f88aca0860100000000001976a9141df8859e60bc679503d16dcb870e6ce91a57e9df88ac00000000\n# Bitcoin transaction id 7e9f0f7d9daa2d9e51b2e22f4abe814c3f90539afa778a9bef88dc64627cb2ec\nsha256 == 9c6aa9591003377455b6f27fc71b5acfa5fbb2fa49362fa87a25ef0d799dd462\n\u0026\n...content omitted...\n\u0026\nprepend 0be23709859913babd4460bbddf8ed213e7c8773a4b1face30f8acfdf093b705 == 0be23709859913babd4460bbddf8ed213e7c8773a4b1face30f8acfdf093b7053f10376d0aebb4647ff550b60d69ba5ad6b6809d51af6a6476e0312a9433a3bf\nsha256 == faa6e88835c144ad73f48992bc05e691a52a9199df02450194f3a03b530dc2d7\nsha256 == 007ee445d23ad061af4a36b809501fab1ac4f2d7e7a739817dd0cbb7ec661b8a\nverify BitcoinBlockHeaderAttestation(358391)\n# Bitcoin block merkle root 8a1b66ecb7cbd07d8139a7e7d7f2c41aab1f5009b8364aaf61d03ad245e47e00\n\n```\n\n#### Verify\n\nVerify the timestamp attestations with the aid of remote block explorers.\n\n```shell\n$ ots-cli.js verify examples/hello-world.txt.ots\nAssuming target filename is 'examples/hello-world.txt'\nSuccess! Bitcoin block 358391 attests existence as of 2015-05-28 CEST\n```\n\nNote: The verification will always try to use the local bitcoin node first and fallback to asking block explorers if it isn't possible. The connection to the node is made by looking for the `bitcoin.conf` file in the default places according to your OS.\nWhen there is no running local node, or the verification happen in the browser (which cannot access to your file system looking for the `bitcoin.conf` file) the verify ask information to the block explores. Verification using block explorers is convenient but not as secure as asking a local node. \n\n#### Upgrade\n\nUpgrade incomplete remote calendar timestamps to be independently verifiable. This command overwrites the file `examples/incomplete.txt.ots` if needed and makes a backup of the old content at `examples/incomplete.txt.ots.bak`. \n\n```shell\n$ ots-cli.js upgrade examples/incomplete.txt.ots\nTimestamp has been successfully upgraded!\nThe file .bak was saved!\nThe file .ots was upgraded\n```\n\n## From code\n\n\u003e Note that from version 0.1.x to 0.2.x basic method interface changed, an upgrade will require change in your code.\n\n#### Stamp\n\nCreate timestamp of a file with the aid of a remote calendar.\n\n```js\nconst OpenTimestamps = require('opentimestamps');\n\nconst file = Buffer.from('5468652074696d657374616d70206f6e20746869732066696c6520697320696e636f6d706c6574652c20616e642063616e2062652075706772616465642e0a','hex');\nconst detached = OpenTimestamps.DetachedTimestampFile.fromBytes(new OpenTimestamps.Ops.OpSHA256(), file);\nOpenTimestamps.stamp(detached).then( ()=\u003e{\n  const fileOts = detached.serializeToBytes();\n});\n```\nConst `file` created from the hex representation of the file `examples/incomplete.txt`\n\n###### Stamp hash\n\nSometimes you don't want to timestamp a file or you already have the sha256 hash of what you want to timestamp. For example, if you want to timestamp the file `examples/incomplete.txt` and you already have its hash you can do this:\n\n```js\nconst hash = Buffer.from('05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9','hex');\ndetached = DetachedTimestampFile.fromHash(new Ops.OpSHA256(), hash);\n```\n\n###### Stamp multiple data at once\n\nIf you have a lot of files to timestamp it is unconvenient to make a calendar request for every file. In this cases you can build a [merkle tree](https://github.com/opentimestamps/javascript-opentimestamps/blob/7429d35011350f4df29c53b45b76b87adff62ee8/src/open-timestamps.js#L205) by your own or call the stamp function with an array for request, behind the curtain the function will make a merkle tree and perform just one call to the calendars.\n\n```js\n  const files = []; /* init this array with the binary contents of the files you want to timestamp */\n  const detaches = [];\n  files.forEach(file =\u003e {\n    const detached = DetachedTimestampFile.fromBytes(new Ops.OpSHA256(), file);\n    detaches.push(detached);\n  });\n  OpenTimestamps.stamp(detaches).then(() =\u003e {\n    ots = [];\n    detaches.forEach((timestamp, i) =\u003e {\n      ots.push( timestamp.serializeToBytes() );\n    });\n  }).catch(err =\u003e {\n    console.error(err);\n  });\n```\n\nThe `ots` array will contain multiple proofs, one for each input.\n\n###### Async Await\n\nIf you prefer the async/await (require Node 7.6+) syntax the promise based API of the library works out of the box:\n\n```js\ngo_async();\n\nasync function go_async() {\n    const hash = Buffer.from('05c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9','hex');\n    const detached = OpenTimestamps.DetachedTimestampFile.fromHash(new OpenTimestamps.Ops.OpSHA256(), hash);\n\n    try {\n        await OpenTimestamps.stamp(detached);\n        const fileOts = detached.serializeToBytes();\n    } catch(err) {\n        console.log(err);\n    }\n\n}\n```\n\n#### Info\n\nShow information on a timestamp.\n\n```js\nconst OpenTimestamps = require('opentimestamps');\nconst fileOts = Buffer.from('004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e70083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f7267','hex');\nconst detached = OpenTimestamps.DetachedTimestampFile.deserialize(fileOts);\nconst infoResult = OpenTimestamps.info(detached);\nconsole.log(infoResult);\n```\n\nConst `fileOts` created from the hex representation of the file `examples/incomplete.txt.ots`. You can match the printed result with the file `test/incomplete.txt.ots.info`.\n\n#### Verify\n \nVerify the timestamp attestations.\n\n```js\nconst OpenTimestamps = require('opentimestamps');\nconst file = Buffer.from('5468697320646f63756d656e742069732074696d657374616d706564206f6e20626f7468204c697465636f696e20616e6420426974636f696e20626c6f636b636861696e73','hex');\nconst fileOts = Buffer.from('004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010832bb24ab386bef01c0656944ecafa2dbb1e4162ced385754419467f9fb6f4d97f010c7c118043ce37d45f1ab81d3cd9dc9aa08fff0109b01031328e457c754a860bc5bc567ab08f02012dbcf25d46d7f01c4bd7c7ebdcd2080974b83a9198bc63cdb23f69c817f110508f0203c6274f7a67007de279fb68938e5549f462043570ccdbc17ba43e632a772d43208f1045ab0daf9f008ad9722b721af69e80083dfe30d2ef90c8e292868747470733a2f2f66696e6e65792e63616c656e6461722e657465726e69747977616c6c2e636f6df010dfd289ba718b4f30bb78191936c762a508f02026503e60c641473ec6f833953d04f7c8a65c5059a44a7e8c01c8cb9fed2ac2b308f1045ab0dafaf008c0c7948d8d5b64cf0083dfe30d2ef90c8e232268747470733a2f2f6c74632e63616c656e6461722e636174616c6c6178792e636f6d','hex');\nconst detached = OpenTimestamps.DetachedTimestampFile.fromBytes(new OpenTimestamps.Ops.OpSHA256(), file);\nconst detachedOts = OpenTimestamps.DetachedTimestampFile.deserialize(fileOts);\nlet options = {};\n// options.ignoreBitcoinNode - Ignore verification with bitcoin node \noptions.ignoreBitcoinNode = true;\n// options.timeout - Adjust the request timeout (default: 1000) \noptions.timeout = 5000;\nOpenTimestamps.verify(detachedOts,detached,options).then(verifyResult =\u003e {\n  // return an object containing timestamp and height for every attestation if verified, undefined otherwise.\n  console.log(verifyResult);\n  // prints:\n  // { bitcoin: { timestamp: 1521545768, height: 514371 },\n  //   litecoin: { timestamp: 1521540398, height: 1388467 } }\n\n});\n```\n\nConst `file` created from the hex representation of the file `examples/ltc-and-btc.txt` while `fileOts` contains `examples/ltc-and-btc.txt.ots`.\n\n#### Upgrade\n\nUpgrade incomplete remote calendar timestamps to be independently verifiable.\n\n```js\nconst OpenTimestamps = require('opentimestamps');\nconst fileOts = Buffer.from('004f70656e54696d657374616d7073000050726f6f6600bf89e2e884e89294010805c4f616a8e5310d19d938cfd769864d7f4ccdc2ca8b479b10af83564b097af9f010e754bf93806a7ebaa680ef7bd0114bf408f010b573e8850cfd9e63d1f043fbb6fc250e08f10457cfa5c4f0086fb1ac8d4e4eb0e70083dfe30d2ef90c8e2e2d68747470733a2f2f616c6963652e6274632e63616c656e6461722e6f70656e74696d657374616d70732e6f7267','hex');\nconst detached = OpenTimestamps.DetachedTimestampFile.deserialize(fileOts);\nOpenTimestamps.upgrade(detached).then((changed) =\u003e {\n    if (changed) {\n      console.log('Timestamp upgraded');\n      const upgradedFileOts = detached.serializeToBytes();\n    } else {\n      console.log('Timestamp not upgraded');\n    }\n}).catch(err =\u003e {\n    console.log(err);\n});\n```\n\n## Pull Requests\n\nPRs are welcome, before reviewing them we wait the travis build concludes successfully, so please check:\n\n*  All tests must pass (`npm test`). (Rarely test fails for networking issue, if you think it's your case ask the maintainers in the comments to relaunch the travis build)\n*  [standard linter](https://github.com/standard/standard) is launched in the build process, any warning found by the linker break the build, so be sure to check warnings by launching `standard` before the commit, most simple errors could be automatically fixed with `standard --fix`\n\n\n## License\n\n[__LGPL3__](https://github.com/opentimestamps/javascript-opentimestamps/blob/master/LICENSE)\n\n\nThe OpenTimestamps Client is free software: you can redistribute it and/or\nmodify it under the terms of the GNU Lesser General Public License as published\nby the Free Software Foundation, either version 3 of the License, or (at your\noption) any later version.\n\nThe OpenTimestamps Client is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\nor FITNESS FOR A PARTICULAR PURPOSE. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentimestamps%2Fjavascript-opentimestamps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopentimestamps%2Fjavascript-opentimestamps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentimestamps%2Fjavascript-opentimestamps/lists"}