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

@cronstamp/clientlib

v0.2.0

Published

Client library for cronstamp, a blockchain-based document timestamping and verification service.

Downloads

99

Readme

cronStamp Client Library

This is a TypeScript client library for cronStamp, the blockchain-based document timestamping and verification service. For an explanation of cronStamp check out this page.

cronStamp websiteGitLabAPI referencenpm package

Installation

npm

In a Node.js environment you can install the cronStamp client library with npm

npm install @cronstamp/clientlib

Once installed, library functions can be imported like this in your typescript project

import { requestCertificateForString } from '@cronstamp/clientlib';

...

CDN

If you are in a browser environment instead, you can directly embed the library from a CDN like so

<script type="module">
  import { requestCertificateForString } from "https://esm.sh/@cronstamp/clientlib";

  ...
</script>

Usage

The two main functionalities of the client library are document timestamping and document verification. Let's walk through each of the two steps with an example.

Timestamp a document

First comes document timestamping, where we provide the document and receive in turn the certificate. Under the hood, the client library hashes the document and submits the hash to the cronStamp HTTP API. cronStamp inserts the hash into each supported blockchain and generates a partial certificate. From this, the client library assembles and returns the full certificate. Afterwards, the client library performs a full document verification to ensure correctness of the certificate.

Let's dive into the full example.

import { requestCertificateForString } from '@cronstamp/clientlib';

let message = 'This is the data that the certificate will be created for.';

let requestResult = await requestCertificateForString(message)
    .onMessage((data) => console.log(data.message))
    .start();

You can run the example in this JSFdiddle.

For simplicity, the example uses a string (the message variable) to represent the document. Calling requestCertificateForString and passing the message returns the timestamping process which is an object of type RequestProcess. This request process object has several methods, such as configure, onMessage, onError, start, and cancel.

We use onMessage to define handlers for processing the result data of type ResultData which is emitted after each step of the timestamping process (for all possible steps see the Step enum). In this case, we simply print the status message. Calling start starts the timestamping process and returns a promise, which has to be awaited and eventually resolves to the requestResult of type ResultData. Calling onMessage is optional and in case of it's absence the entire ResultData object is logged to console for each process step.

After successful execution of th example, the requestResult object looks as follows with the final certificate in the currentCert field. The step is set to 7 corresponding to Step.REQUEST_FULLCERT_SUCCESS.

{
  step: 7,
  type: 0,
  currentCert: {
    version: 1,
    hash_algorithm: 'SHA-256',
    blockchains: {
      xrp: {
        transaction: '0E128CBFD3FA4E6D9BA6C8061CBFD3C56D4973A89CBF98C5B77465FA805B68F6',
        block_timestamp: 777154992
      }
    },
    merkle_tree_splice: [],
    is_merkle_tree: false,
    document_hash: '2xXmxEInHGanIixLeS28kOBomIYWuuFKWsFnceNwRQI=',
    salt: '1b60e79985d45c7d853d52c8238092ab',
    salted_hash: 'TxwxZNDPRqbhgQebukA49aSsw+X+IIt+hOi7X2RUbh0='
  },
  message: 'Certificate created and verified successfully!',
  additionalDataType: 0,
  additionalData: undefined,
  inputData: {
    type: 0,
    data: 'This is the data that the certificate will be created for.',
    is_merkle_tree: false,
    certFileName: 'This is the data tha',
    displayName: 'This is the dat[...]'
  },
  currentTime: 2024-08-16T20:23:17.141Z
}

In addition to requestCertificateForString, the client library also provides a method requestCertificateForFile which takes a file, and requestCertificateForHash which takes a hash, in case you want to hash the document on your own. There is also the generic method requestCertificate which works for all three types of inputs.

Verify a document

Document verification requires as inputs the document and the certificate and returns whether the document has been modified since the timestamping or not. To this end, the client library hashes the document (together with the hashes in the merkletree splice) and compares this hash with the one stored on each blockchain. If the hashes match for all blockchains, the document is verified, i.e., has not been modified. Document verification takes place on client-side only and requires no connection to the cronStamp servers.

Let's see an example of how document verification with the client library works. You can also find the example in this JSFiddle.

import { type Certificate, Step, verifyCertificateForString } from '@cronstamp/clientlib';

let message = 'This is the data that the certificate will be created for.';

let certificate: Certificate = {
	version: 1,
	hash_algorithm: 'SHA-256',
	blockchains: {
		xrp: {
			transaction: '8076BF4F96DE57EF64B151FC28C78A66BD2FA29E88D22B923A6775D4B383A893',
			block_timestamp: 777221110
		}
	},
	merkle_tree_splice: [
		'VB6i9EGb5v8e5+8klTyPofAr60PFJMZGEDW0u1/eH2Y=',
		'gJAjot3ZI113UvuanaBBznWRJqpTLpztOWhImxZx0v8=',
		'FzmiHQphqpqnbxkA5aykX8gt2Q55Gtp2AAbNUrAAPDw=',
		'sj8Sx5llDnx/36qJogZ8YwX1A9LpVEY2DwJYBschke8=',
		'6zJvCdGG5iLggdSj36WF+NCOh9XA20DrAHnrHosOSPg='
	],
	is_merkle_tree: false,
	document_hash: '2xXmxEInHGanIixLeS28kOBomIYWuuFKWsFnceNwRQI=',
	salt: '105f1cd76154e00f29d36b4966ce9ff4',
	salted_hash: 'seUNhKbRhndxYXdH9VA+Ii3IjlnUit0R722ooItjFz8='
};

let verificationResult = await verifyCertificateForString(certificate, message)
    .onMessage((data) => console.log(data.message))
    .start();

The document is again represented by the string in the message variable. The certificate is defined as instance of the Certificate type. Both message and certificate are passed to verifyCertificateForString, which returns a VerificationProcess instance. The VerificationProcess has the same methods as the RequestProcess, i.e., configure, onMessage, onError, start, and cancel. Here, we define again a handler for logging the status message and start the verification process by calling start.

When executing the example the last two status messages in the console indicate that the document is verified successfully, i.e., has not been modified since timestamping.

...
The certificate is valid! The hash in the blockchain and certificate match. This means the document existed at time 2024-08-17T14:45:10.000Z
Verified root hash successfully in 1 blockchains.

The verificationResult object looks like this with step 13 corresponding to Step.VERIFICATION_FULL_SUCCESS. Also note the additionalData field that holds additional information specific to the step, in this case the unix timestamp of the blockchain block containing the document hash. What type of information is present in the additionalData field is indicated by the additionalDataType field that takes a value of the AdditionalDataType enum. Here, the value is 6 corresponding to AdditionalDataType.TIMESTAMP.

{
  step: 13,
  type: 0,
  currentCert: {
    version: 1,
    hash_algorithm: 'SHA-256',
    blockchains: undefined,
    merkle_tree_splice: [
      'VB6i9EGb5v8e5+8klTyPofAr60PFJMZGEDW0u1/eH2Y=',
      'gJAjot3ZI113UvuanaBBznWRJqpTLpztOWhImxZx0v8=',
      'FzmiHQphqpqnbxkA5aykX8gt2Q55Gtp2AAbNUrAAPDw=',
      'sj8Sx5llDnx/36qJogZ8YwX1A9LpVEY2DwJYBschke8=',
      '6zJvCdGG5iLggdSj36WF+NCOh9XA20DrAHnrHosOSPg='
    ],
    is_merkle_tree: false,
    document_hash: '2xXmxEInHGanIixLeS28kOBomIYWuuFKWsFnceNwRQI=',
    salt: '105f1cd76154e00f29d36b4966ce9ff4',
    salted_hash: 'seUNhKbRhndxYXdH9VA+Ii3IjlnUit0R722ooItjFz8='
  },
  message: 'Verified root hash successfully in 1 blockchains.',
  additionalDataType: 6,
  additionalData: 1723905910000,
  inputData: {
    type: 0,
    data: 'This is the data that the certificate will be created for.',
    is_merkle_tree: false,
    certFileName: 'This is the data tha',
    displayName: 'This is the dat[...]'
  },
  currentTime: 2024-08-17T14:55:28.781Z
}

You can use the value in the step field of the verificationResult object like this to determine whether verification was successful

if (verificationResult.step == Step.VERIFICATION_FULL_SUCCESS) {
	console.log(`Document verified successfully.`);
} else {
	console.log(`Error during certificate verification: ${verificationResult.message}`);
}

Check out this JSFiddle to see what happens if you run verification on a modified document.

The last line of console output is "Error during certificate verification: Locally calculated data hash does not match hash in provided certificate: 9OI5T+j0wCi9Fp31xTBbkUkY3sguo4b69RBAngP0KYM= != 2xXmxEInHGanIixLeS28kOBomIYWuuFKWsFnceNwRQI=" indicating a mismatch of the calculated document hash and the hash stored in the blockchain. The client library correctly detects that the document has been modified.

Customize error handling

Similar to onMessage, the RequestProcess and VerificationProcess objects returned by requestCertificate and verifyCertificate have an optional onError method. With this you can define a custom handler for processing the ResultData object emitted in case of an error. If onError is not called the handler defined by onMessage is used as a fallback in case of an error.

Customize configuration

You can customize the default settings of the client library by calling configure on the RequestProces or VerificationProcess with a configuration object as shown in the example below. Note that all values in the configuration object are optional, i.e. you could also provide a partial configuration to update only a subset of the settings.

import { requestCertificateForString, CronStampConfig, LOG_LEVELS } from '@cronstamp/clientlib';

export const customConfig: CronStampConfig = {
	LOG_LEVEL: LOG_LEVELS.WARN,
	BLOCKCHAIN_XRP_SERVER: 'wss://testnet.xrpl-labs.com',
	BLOCKCHAIN_SOLANA_SERVER: 'devnet',
	API_URL: 'https://api.cronstamp.com',
	CERT_REQUEST_TIMEOUT: 100,
	CERT_REQUEST_INTERVAL: 3
};

let requestResult = await requestCertificateForString('some message')
    .configure(customConfig)
    .start();

The default settings can be found here.