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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@witniumtech/chain-sdk

v0.8.0

Published

TypeScript SDK for the WitniumChain API - create and verify blockchain witnesses

Readme

@witnium/chain-sdk

TypeScript SDK for the WitniumChain API. Create blockchain witnesses with a simple one-liner.

Installation

# From npm (recommended)
npm install @witniumtech/chain-sdk

# From GitHub Packages
npm install @witnium/chain-sdk

Getting Started

1. Generate a keypair

import { generateKeyPair } from '@witniumtech/chain-sdk';

const { publicKey, privateKey } = generateKeyPair();
console.log('Public key:', publicKey);   // Share this with the WitniumChain admin
console.log('Private key:', privateKey); // Store securely — never share this

2. Get your contract deployed

Send your public key to the WitniumChain admin. They will deploy a smart contract configured with your key and give you back a contract address (e.g. 0x1234...).

3. Create witnesses

import { WitniumChainClient } from '@witniumtech/chain-sdk';

const client = new WitniumChainClient({
  baseUrl: 'https://api.witniumchain.com',
  contractAddress: '0x...', // From step 2
  signingPrivateKey: privateKey,
});

const result = await client.createWitness([
  { key: 'fileHash', value: 'sha256:abc123...' },
  { key: 'filename', value: 'document.pdf' },
]);

console.log('Witness ID:', result.witnessId);
console.log('Transaction:', result.transactionHash);

The SDK handles all the complexity internally:

  • Computing a SHA256 hash of your data locally (the raw data never leaves your system)
  • Two-step prepare/finalize flow
  • Ed25519 signature generation

Key Generation

import { generateKeyPair, getPublicKey } from '@witniumtech/chain-sdk';

// Generate a new keypair
const { publicKey, privateKey } = generateKeyPair();

// Derive public key from an existing private key
const pub = getPublicKey(privateKey);
console.log(pub === publicKey); // true

Both functions use the Node.js crypto module (Ed25519). Keys are returned as 64-character hex strings (32 bytes).

API Reference

Creating Witnesses

// Fire-and-forget (returns immediately after transaction broadcast)
const result = await client.createWitness([
  { key: 'fileHash', value: 'sha256:abc123...' },
  { key: 'filename', value: 'document.pdf' },
]);

// With witness chaining
const result = await client.createWitness(data, {
  previousWitnessId: 'abc123...', // Link to previous version
});

// Wait for blockchain confirmation
const confirmed = await client.createWitnessAndWait([
  { key: 'fileHash', value: 'sha256:abc123...' },
]);
console.log('Confirmed at block:', confirmed.blockNumber);

Checking Transaction Status

// Poll for confirmation manually
const status = await client.transactions.getStatus(result.transactionHash);
if (status.success && status.data.status === 'confirmed') {
  console.log('Confirmed at block:', status.data.blockNumber);
}

// Get detailed transaction info
const details = await client.transactions.getDetails(result.transactionHash);

Querying Witnesses

// Get a witness from the blockchain (uses client's configured contract address)
const witness = await client.witnesses.get(witnessId);
if (witness.success) {
  console.log('Data ID:', witness.data.dataId);
  console.log('Timestamp:', witness.data.timestamp);
  console.log('Signature R:', witness.data.signatureR);
  console.log('Signature S:', witness.data.signatureS);
}

Validating Witnesses

The validate() method fetches comprehensive blockchain data for witness validation in a single call:

// Validate a witness with full blockchain details
const validation = await client.witnesses.validate(witnessId, transactionHash);
if (validation.success && validation.data.exists) {
  // Witness data
  console.log('Witness ID:', validation.data.witness.witnessId);
  console.log('Data ID:', validation.data.witness.dataId);
  console.log('Block:', validation.data.witness.blockNumber);

  // Transaction details
  console.log('TX Hash:', validation.data.transaction.transactionHash);
  console.log('Gas Used:', validation.data.transaction.gasUsed);

  // Network/chain status
  console.log('Network:', validation.data.network.networkName);
  console.log('Platform:', validation.data.network.platform);
  console.log('Consensus:', validation.data.network.consensus);
  console.log('Current Block:', validation.data.network.currentBlockNumber);
  console.log('Confirmations:', validation.data.network.confirmations);
  console.log('Block Time:', validation.data.network.blockTimeSeconds, 'seconds');
  console.log('Chain Status:', validation.data.network.status);

  // Contract info
  console.log('Public Key:', validation.data.contract.signingPublicKey);
  console.log('Total Witnesses:', validation.data.contract.totalWitnessCount);
}

The validation response includes:

  • Witness data: witnessId, dataId, timestamp, blockNumber, nonce, signatures, contractVersion
  • Transaction details: hash, block info, gas costs, addresses
  • Network status: current block, confirmations, chain health, platform info (Hyperledger Besu, QBFT consensus)
  • Contract info: signing public key, total witness count

Note: The actual witnessed data (key-value pairs) and data signature are stored off-chain. To complete validation, verify that SHA256(yourWitnessedData) === validation.data.witness.dataId.

Chain Status

Get live network status — the same data shown on the Grafana WitniumChain Overview dashboard. This is a public endpoint (no authentication required).

const status = await client.status.get();
if (status.success) {
  // Chain metrics
  console.log('Block height:', status.data.chain.blockHeight);
  console.log('Avg block time:', status.data.chain.avgBlockTimeSeconds, 's');
  console.log('Blocks (5 min):', status.data.chain.blocksLast5Min);

  // Validators
  console.log('Validators:', status.data.validators.online, '/', status.data.validators.total);
  for (const node of status.data.validators.nodes) {
    console.log(`  ${node.name}: ${node.status} block=${node.blockHeight} peers=${node.peerCount}`);
  }

  // Network
  console.log('Total peers:', status.data.network.totalPeers);
  console.log('Block spread:', status.data.network.blockHeightSpread);
  console.log('TX pool:', status.data.network.transactionPool.size);
}

// Get time series history for charts
const history = await client.status.getHistory('1h'); // '1h' | '6h' | '24h' | '7d'
if (history.success) {
  console.log('Data points:', history.data.chain.timestamps.length);
  console.log('Block heights:', history.data.chain.blockHeight);
  console.log('Peer counts:', history.data.network.totalPeers);
}

Querying Contracts

// Get contract info
const info = await client.contracts.getInfo(contractAddress);

// Get witness count
const count = await client.contracts.getWitnessCount(contractAddress);

// Get signing public key
const key = await client.contracts.getSigningPublicKey(contractAddress);

Querying Wallet Balances

// Get wallet balance
const balance = await client.wallets.getBalance('0x...');
if (balance.success) {
  console.log('Balance:', balance.data.balanceEth, 'ETH');
  console.log('Balance (Wei):', balance.data.balanceWei);
}

// Check if wallet needs funding
if (balance.success && parseFloat(balance.data.balanceEth) < 0.1) {
  console.warn('Wallet balance low - may need funding');
}

Ethereum Mainnet Anchoring

Witnesses are periodically anchored to Ethereum mainnet for additional security.

// Verify a witness is anchored
const verification = await client.anchors.verify(witnessId);
if (verification.data.verified) {
  console.log('Anchored in:', verification.data.anchor.anchorId);
  console.log('Ethereum TX:', verification.data.anchor.ethereumTxHash);
}

// List all anchors
const anchors = await client.anchors.list({ page: 1, limit: 10 });

Admin Client

The WitniumChainAdminClient provides contract provisioning and wallet management for server-side applications with admin access.

Setup

import { WitniumChainAdminClient } from '@witniumtech/chain-sdk';

const admin = new WitniumChainAdminClient({
  baseUrl: 'https://api.witniumchain.com',
  adminToken: process.env.WITNIUMCHAIN_ADMIN_TOKEN!,
});

Provision a Contract (Full Onboarding)

// Auto-generates a keypair, deploys the contract, and returns everything
const result = await admin.provisionContract({ contractId: 'workspace-123' });

console.log('Contract:', result.contractAddress);
console.log('Private key:', result.signingKeyPair!.privateKey); // Store securely!

// Use the result directly to create a regular client
const client = new WitniumChainClient(result.clientConfig!);
const witness = await client.createWitness([{ key: 'hello', value: 'world' }]);

Or provide your own public key:

const result = await admin.provisionContract({
  contractId: 'workspace-456',
  signingPublicKey: existingPublicKey, // 64 hex chars
  metadata: { team: 'engineering' },
});
// result.signingKeyPair is null (caller manages their own key)
// result.clientConfig is null (caller builds their own config)

Low-Level Admin Methods

// Deploy a contract
const deploy = await admin.deployContract({
  contractId: 'my-contract',
  signingPublicKey: publicKey,
});

// Fund a wallet
const fund = await admin.fundWallet({
  walletAddress: '0x...',
  amountEth: '10.0',
});

// Get contract info
const info = await admin.getContractInfo('0x...');

Configuration

const client = new WitniumChainClient({
  // Required
  baseUrl: 'https://api.witniumchain.com',
  contractAddress: '0x1234...',
  signingPrivateKey: 'ed25519-private-key-hex', // 64 or 128 hex chars

  // Optional
  token: 'bearer-token',  // For endpoints that require auth
  timeout: 60000,         // Request timeout in ms (default: 30000)
  fetch: customFetch,     // Custom fetch implementation
});

Key Management

Use generateKeyPair() to create a new Ed25519 keypair, or bring your own key. The private key:

  • Never leaves your system — only signatures and data hashes are sent to the API
  • Should be stored securely (e.g., environment variables, secrets manager)

Accepted private key formats:

  • 64 hex chars (32 bytes) - seed format (output of generateKeyPair())
  • 128 hex chars (64 bytes) - NaCl format (seed + public key)

Privacy-First Architecture

The raw witness data never leaves your system. The SDK computes dataId = SHA256(canonicalized data) locally and only sends the hash to the API. This means:

  • The API acts as a pure notary — it timestamps and signs hashes without ever seeing the underlying data
  • Your data stays private even in transit
  • You can independently verify a witness by recomputing SHA256(yourData) and comparing with the on-chain dataId

Use computeDataId() to compute the hash independently:

import { computeDataId } from '@witniumtech/chain-sdk';

const dataId = computeDataId([
  { key: 'fileHash', value: 'sha256:abc123...' },
  { key: 'filename', value: 'document.pdf' },
]);
// dataId is a 64-char hex SHA256 hash — compare with the on-chain value

Quadruple-Layer Protection

Every witness is protected by four independent cryptographic layers:

  1. Data Signature - Your Ed25519 signature of the data hash (computed locally)
  2. Witness Signature - Your Ed25519 signature of the witness payload (stored on blockchain)
  3. SHA256 Hash - Data ID is computed client-side from the canonicalized data
  4. Blockchain Seal - Immutable record with growing confirmations

Error Handling

try {
  const result = await client.createWitness(data);
} catch (error) {
  if (error instanceof WitniumApiError) {
    console.error('API Error:', error.message);
    console.error('Status:', error.status);
    console.error('Code:', error.code);
  }
}

Advanced: Low-Level API

For full control, you can use the low-level prepare/finalize methods:

import { computeDataId, signMessage, parsePrivateKey } from '@witniumtech/chain-sdk';

const seed = parsePrivateKey(privateKeyHex);

// Step 1: Compute dataId and sign it
const dataId = computeDataId(yourData);
const dataSignature = signMessage(dataId, seed);

// Step 2: Prepare (API only receives the hash)
const prepare = await client.witnesses.prepare(contractAddress, {
  dataId,
  dataSignature,
});

// Step 3: Sign witness payload and finalize
const finalize = await client.witnesses.finalize(witnessId, {
  witnessSignature: 'your-signature',
});

Complete Resource Reference

The SDK provides the following resource namespaces:

| Resource | Description | Key Methods | |----------|-------------|-------------| | client.witnesses | Create, query, and validate witnesses | prepare(), finalize(), get(), validate() | | client.transactions | Query transaction status | getStatus(), getDetails() | | client.contracts | Query contract info | getInfo(), verify(), getWitnessCount(), getSigningPublicKey() | | client.anchors | Ethereum anchoring | list(), getLatest(), get(), verify(), verifyOnChain(), getSchedulerStatus(), getEthereumHealth() | | client.wallets | Query wallet balances | getBalance() | | client.health | API health checks | check() | | client.status | Chain status (Grafana dashboard data) | get(), getHistory() |

Admin Client

| Method | Description | |--------|-------------| | admin.provisionContract(options) | Full onboarding: generate keypair + deploy + verify | | admin.deployContract(request) | Deploy a WitnessRegistry contract | | admin.fundWallet(request) | Fund a wallet with ETH | | admin.getContractInfo(address) | Get contract info |

High-Level Methods

For common operations, use the high-level client methods:

| Method | Description | |--------|-------------| | client.createWitness(data, options?) | Create a witness (fire-and-forget) | | client.createWitnessAndWait(data, options?) | Create and wait for confirmation |

All Response Types

All API responses return ApiResult<T>:

type ApiResult<T> =
  | { success: true; data: T; status: number }
  | { success: false; error: ApiError };

Always check result.success before accessing result.data.

Requirements

  • Node.js 18+ (uses native Ed25519 crypto)
  • For browser usage, use the low-level API with your own signing implementation

License

MIT