@witniumtech/chain-sdk
v0.6.0
Published
TypeScript SDK for the WitniumChain API - create and verify blockchain witnesses
Maintainers
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-sdkQuick Start
// Import matches your install source
import { WitniumChainClient } from '@witniumtech/chain-sdk'; // npm
// import { WitniumChainClient } from '@witnium/chain-sdk'; // GitHub Packages
const client = new WitniumChainClient({
baseUrl: 'https://api.witniumchain.com',
contractAddress: '0x...', // Your deployed contract
signingPrivateKey: 'your-ed25519-private-key-hex',
});
// Create a witness - that's it!
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:
- Canonicalizing and signing the data
- Two-step prepare/finalize flow
- Ed25519 signature generation
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 });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
The SDK requires your Ed25519 private key for signing witnesses. This key:
- Never leaves your system
- Only signatures are sent to the API
- Should be stored securely (e.g., environment variables, secrets manager)
The private key can be:
- 64 hex chars (32 bytes) - seed format
- 128 hex chars (64 bytes) - NaCl format (seed + public key)
Quadruple-Layer Protection
Every witness is protected by four independent cryptographic layers:
- Data Signature - Your Ed25519 signature of the witnessed data
- Witness Signature - Your Ed25519 signature of the witness payload (stored on blockchain)
- SHA256 Hash - Data ID is a hash of the canonicalized data
- 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:
// Step 1: Prepare
const prepare = await client.witnesses.prepare(contractAddress, {
data: [...],
dataSignature: 'your-signature',
});
// Step 2: 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() |
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
