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

@anchora/sdk

v2.4.0

Published

Official JavaScript SDK for Anchora VaaS - Blockchain Data Anchoring Platform (with Hybrid API v2.0, Key Management)

Readme

Anchora SDK

npm version License: MIT Node TypeScript

Official JavaScript / TypeScript SDK for Anchora — anchor any data hash to the Polygon blockchain, verify integrity later, and detect tampering with zero data exposure.

Built for developers shipping audit-grade, tamper-evident records in healthcare, finance, supply chain, document verification, and any domain where data integrity matters more than storage.

Installation

npm install @anchora/sdk

Requires Node.js 14+. Works in modern browsers and Node.js. TypeScript types are bundled — no @types/* package needed.

Quick Start

const { AnchoraClient } = require('@anchora/sdk');

// Initialize client
const anchora = new AnchoraClient({
  apiKey: 'your-api-key',
  projectId: 'your-project-id'
});

// Anchor data to blockchain
const result = await anchora.anchor({
  orderId: 'ORD-12345',
  total: 999.99,
  timestamp: Date.now()
});

console.log('Data anchored:', result.hash);

Features

  • Hash-only mode — anchor a SHA-256 hash without sending your data anywhere (the most private and recommended mode)
  • Blockchain proof — every record is provably anchored on Polygon, batched via Merkle tree for ~$0.000007 per record
  • Canonical hashing — deterministic SHA-256 over JSON (byte-identical to the server)
  • AES-256-GCM encryption — built-in with PBKDF2 key derivation (100k iterations) when you need to store data
  • File support — upload + hash + verify documents (PDF, images, DOCX, etc.) up to 50MB
  • Batch operations — anchor up to 100 records in a single API call
  • Tamper detection — verify on read; mismatches throw with a clear error
  • Webhook callbacks — get notified when batches are anchored on-chain
  • Auto-retry — exponential backoff on transient failures
  • TypeScript types — full .d.ts bundled
  • Audited cryptography — uses @noble/curves for X25519 / Ed25519 (Signal-style key management)

Use cases

  • Tamper-evident audit logs — anchor every record write; prove later that history wasn't rewritten
  • Document authenticity — university certificates, medical reports, legal contracts (verify with a single hash)
  • Supply chain integrity — anchor shipment milestones; prove provenance at delivery
  • Regulatory compliance — immutable, third-party-verifiable record of what happened when

Configuration

const anchora = new AnchoraClient({
  apiKey: 'dcp_live_...',           // Required: Your API key
  projectId: 'proj_...',             // Optional: Project ID
  baseURL: 'https://api.anchora.co.in', // Optional: Custom API URL (defaults to production)
  timeout: 30000,                    // Optional: Request timeout (ms)
  retries: 3,                        // Optional: Number of retries
  retryDelay: 1000                   // Optional: Retry delay (ms)
});

Core Methods

anchor(data, options)

Anchor data to the blockchain. The Anchora API computes the hash automatically.

Traditional Mode (Default) - Stores data in Anchora:

const result = await anchora.anchor(
  {
    userId: 'user-123',
    action: 'purchase',
    amount: 50.00
  },
  {
    metadata: { source: 'web-app' },
    webhookUrl: 'https://yourapp.com/webhook',  // Optional: Get notified when anchored
    hashOnly: false  // Default: stores data in Anchora
  }
);

// Returns:
// {
//   success: true,
//   message: 'Hash queued for anchoring',
//   hash: '3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b',
//   recordId: 'rec_...',
//   status: 'QUEUED',
//   hashOnly: false,
//   estimatedAnchorTime: '30 seconds',
//   queuedAt: '2025-11-28T10:30:00.000Z'
// }

Hash-Only Mode - Maximum privacy, no data stored in Anchora:

const result = await anchora.anchor(
  {
    certificateId: 'CERT-2025-001',
    studentName: 'John Doe',
    course: 'Computer Science'
  },
  {
    collection: 'certificates',
    hashOnly: true  // ← Only hash stored, not data
  }
);

// Returns:
// {
//   success: true,
//   message: 'Hash queued for anchoring',
//   hash: 'abc123...',
//   recordId: 'rec_...',
//   status: 'QUEUED',
//   hashOnly: true,
//   note: 'Hash-only mode: Data not stored, only hash anchored to blockchain',
//   estimatedAnchorTime: '30 seconds',
//   queuedAt: '2025-11-28T10:30:00.000Z'
// }

// YOU MUST store the data in YOUR database:
await db.collection('certificates').insertOne({
  certificateId: 'CERT-2025-001',
  studentName: 'John Doe',
  course: 'Computer Science',
  vaas: {
    hash: result.hash,
    recordId: result.recordId
  }
});

verify(data, options)

Verify data integrity against blockchain. Computes hash and checks for tampering.

// Basic verification (checks hash only)
const result = await anchora.verify({
  userId: 'user-123',
  action: 'purchase',
  amount: 50.00
});

// Full verification (with Merkle proof)
const result = await anchora.verify(
  {
    userId: 'user-123',
    action: 'purchase',
    amount: 50.00
  },
  {
    hash: 'e3b0c442...',  // Expected hash
    blockNumber: 29496609,  // Block number
    merkleProof: ['0x123...', '0xabc...']  // Merkle proof
  }
);

// Returns (if verified):
// {
//   success: true,
//   verified: true,
//   status: 'VERIFIED',
//   message: 'Data integrity verified with Merkle proof',
//   hash: '3a7bd3e2...',
//   blockNumber: 29496609,
//   merkleRoot: '0x9876...',
//   verifiedAt: '2025-11-28T10:30:00.000Z'
// }

// Returns (if tampered):
// {
//   success: false,
//   verified: false,
//   status: 'TAMPERED',
//   message: 'Data has been modified. Hash mismatch.',
//   providedHash: 'e3b0c442...',
//   computedHash: 'd7a8fbb3...'
// }

getProof(hash)

Get blockchain proof for a hash.

const proof = await anchora.getProof('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');

// Returns:
// {
//   success: true,
//   hash: 'e3b0c442...',
//   status: 'ANCHORED',
//   proof: {
//     blockNumber: 29496609,
//     transactionHash: '0xb706858a...',
//     merkleProof: ['0x1234...', '0xabcd...'],
//     batchId: 30,
//     anchoredAt: '2025-11-25T10:00:30Z'
//   },
//   metadata: {
//     recordType: 'invoice'
//   }
// }

getBatch(batchId)

Get batch information.

const result = await anchora.getBatch(30);

// Returns:
// {
//   success: true,
//   batch: {
//     batchId: 30,
//     merkleRoot: '0x9876543210fedcba...',
//     recordCount: 256,
//     actualRecordCount: 256,
//     blockNumber: 29496609,
//     transactionHash: '0xb706858a2c9e4a8e3d5f9c1a2b3d4e5f...',
//     gasUsed: 118330,
//     cost: 0.0018,
//     status: 'ANCHORED',
//     anchoredAt: '2025-11-25T10:00:30Z',
//     createdAt: '2025-11-25T10:00:00Z'
//   }
// }

anchorBatch(records, options)

Anchor multiple records at once (up to 100 records per batch). Efficient for bulk operations.

// Basic batch anchoring
const result = await anchora.anchorBatch([
  {
    data: { orderId: 'ORD-001', total: 100.00 },
    collection: 'orders',
    metadata: { source: 'web-app' }
  },
  {
    data: { orderId: 'ORD-002', total: 250.00 },
    collection: 'orders'
  },
  {
    data: { orderId: 'ORD-003', total: 75.50 },
    collection: 'orders'
  }
], {
  webhookUrl: 'https://yourapp.com/webhook/batch'  // Optional: Single webhook for all
});

// Returns:
// {
//   success: true,
//   message: 'Batch anchoring completed',
//   batchId: 'batch_1735131234567_abc123',
//   totalRecords: 3,
//   results: [
//     {
//       success: true,
//       index: 0,
//       recordId: 'rec_xyz1',
//       hash: 'abc123...',
//       status: 'QUEUED',
//       collection: 'orders',
//       encrypted: false
//     },
//     // ... more results
//   ],
//   summary: {
//     successful: 3,
//     failed: 0
//   }
// }

Batch with encryption:

const result = await anchora.anchorBatch([
  {
    data: { patientId: 'P-001', diagnosis: 'Diabetes' },
    collection: 'medical',
    encrypt: true,
    encryptionKey: anchora.generateEncryptionKey(32)
  },
  {
    data: { patientId: 'P-002', diagnosis: 'Hypertension' },
    collection: 'medical',
    encrypt: true,
    encryptionKey: anchora.generateEncryptionKey(32)
  }
]);

Mixed batch (encrypted + plain + hash-only):

const result = await anchora.anchorBatch([
  {
    data: { invoiceId: 'INV-001', amount: 1000 },
    collection: 'invoices'
  },
  {
    data: { ssn: '123-45-6789', name: 'John Doe' },
    collection: 'sensitive',
    encrypt: true,
    encryptionKey: anchora.generateEncryptionKey(32)
  },
  {
    data: { productId: 'PROD-001', price: 99.99 },
    collection: 'products',
    hashOnly: true
  }
]);

Options:

  • records (Array, required) - Array of records to anchor (max 100)
    • data (Object, required) - Data to anchor
    • collection (String, optional) - Collection name
    • metadata (Object, optional) - Additional metadata
    • encrypt (Boolean, optional) - Enable encryption
    • encryptionKey (String, required if encrypt=true) - Encryption key
    • hashOnly (Boolean, optional) - Store only hash
    • webhookUrl (String, optional) - Per-record webhook URL
  • webhookUrl (String, optional) - Global webhook URL for all records

Benefits:

  • ⚡ Faster than individual anchoring
  • 💰 More cost-effective
  • 📊 Individual success/failure tracking
  • 🔄 Failed records don't block successful ones
  • 📦 Single API call for bulk operations

getHealth()

Get system health status and monitor dependencies.

const health = await anchora.getHealth();

// Returns:
// {
//   status: 'healthy',  // or 'degraded', 'unhealthy'
//   service: 'Anchora API',
//   version: '1.0.0',
//   timestamp: '2025-12-25T10:00:00Z',
//   checks: {
//     mongodb: {
//       status: 'connected',
//       state: 'connected',
//       database: 'anchoradb'
//     },
//     redis: {
//       status: 'connected',
//       state: 'ready'
//     },
//     worker: {
//       status: 'healthy'
//     }
//   },
//   responseTime: '45ms'
// }

Use cases:

  • Health monitoring dashboards
  • Uptime checks
  • Dependency status tracking
  • Performance monitoring

File Operations

Upload, hash, and verify files (documents, images, logs) directly through Anchora.

Supported File Formats

  • Documents: PDF, DOCX, TXT, JSON
  • Images: JPG, JPEG, PNG
  • Logs: LOG files
  • Max Size: 50MB per file

Hash File Locally

// Hash a file without uploading
const result = await anchora.hashFile('./certificate.pdf');

console.log('Hash:', result.hash);
console.log('File:', result.fileInfo.name);
console.log('Size:', result.fileInfo.sizeInMB, 'MB');
console.log('Type:', result.fileInfo.mimeType);

// Hash from Buffer
const fs = require('fs');
const buffer = fs.readFileSync('./certificate.pdf');
const bufferResult = await anchora.hashFile(buffer);

Upload and Anchor File

// Upload file to Anchora and anchor to blockchain
const result = await anchora.anchorFile('./certificate.pdf', {
  metadata: {
    studentId: 'STU12345',
    degree: 'Bachelor of Science',
    issueDate: '2025-05-15'
  },
  collection: 'university_certificates'
});

console.log('Record ID:', result.recordId);
console.log('Hash:', result.hash);
console.log('Status:', result.status); // QUEUED
console.log('File Info:', result.fileInfo);

Verify File

// Verify file hasn't been tampered with
const verification = await anchora.verifyFile(
  './certificate.pdf',
  expectedHash
);

if (verification.hashMatches) {
  console.log('✅ File is authentic');
  
  if (verification.blockchainVerification?.verified) {
    console.log('✅ Verified on blockchain');
  }
} else {
  console.log('❌ File has been tampered with');
}

Get File Upload Info

// Get supported formats and limits
const info = await anchora.getFileUploadInfo();

console.log('Supported:', info.supportedFormats);
console.log('Max Size:', info.maxFileSizeInMB, 'MB');

Real-World Use Case: University Certificates

// Step 1: University uploads certificate
const cert = await anchora.anchorFile('./student-cert.pdf', {
  metadata: {
    studentId: 'STU12345',
    studentName: 'John Doe',
    degree: 'Bachelor of Science',
    graduationDate: '2025-05-15',
    issuer: 'University of Technology'
  },
  collection: 'certificates'
});

// Step 2: Student shares certificate + hash with employer
// Step 3: Employer verifies certificate
const verify = await anchora.verifyFile('./student-cert.pdf', cert.hash);

if (verify.hashMatches && verify.blockchainVerification?.verified) {
  console.log('✅ Certificate is authentic and verified on blockchain');
}

Hash-Only Mode (Maximum Privacy)

Hash-only mode allows you to anchor data without storing it in Anchora - perfect for sensitive data and GDPR compliance.

When to Use Hash-Only Mode

Use hash-only mode when:

  • Handling sensitive/private data
  • GDPR/compliance requirements
  • You want full data ownership
  • Cost optimization needed
  • Building stateless architecture

Use traditional mode when:

  • Public data (certificates, documents)
  • Convenience over privacy
  • Anchora-managed verification

Hash-Only Example

// 1. Anchor with hash-only mode
const result = await anchora.anchor(
  {
    patientId: 'P-12345',
    diagnosis: 'Confidential',
    treatment: 'Confidential'
  },
  {
    collection: 'medical-records',
    hashOnly: true  // ← Only hash stored in Anchora
  }
);

// 2. YOU store the data in YOUR database
await db.collection('medical-records').insertOne({
  patientId: 'P-12345',
  diagnosis: 'Confidential',
  treatment: 'Confidential',
  vaas: {
    hash: result.hash,
    recordId: result.recordId
  }
});

// 3. Later, verify with YOUR data
const record = await db.collection('medical-records').findOne({ patientId: 'P-12345' });

const verification = await anchora.verify(record, {
  hash: record.vaas.hash
});

console.log('Data verified:', verification.verified);

Benefits

  • 🔒 Privacy: Data never leaves your infrastructure
  • 👤 Ownership: You control all data
  • ⚖️ Compliance: GDPR-compliant by design
  • 💰 Cost: 60-93% storage reduction
  • 🏗️ Architecture: Stateless service (like OpenAI API)

Webhook Management

getWebhooks(options)

Get webhook delivery history with filtering and pagination.

const webhooks = await anchora.getWebhooks({
  status: 'FAILED',      // Filter by status: PENDING, SENT, FAILED
  startDate: '2025-12-01T00:00:00Z',
  endDate: '2025-12-25T23:59:59Z',
  limit: 50,
  offset: 0,
  collection: 'orders'
});

console.log('Total webhooks:', webhooks.pagination.total);
console.log('Summary:', webhooks.summary);
// { PENDING: 10, SENT: 130, FAILED: 10 }

webhooks.data.forEach(webhook => {
  console.log(`${webhook.hash} - ${webhook.webhookStatus}`);
});

retryWebhook(recordId)

Manually retry a failed webhook delivery (max 5 retries).

try {
  const result = await anchora.retryWebhook('abc123');
  
  console.log('Webhook sent:', result.webhookStatus); // SENT
  console.log('Retry count:', result.retryCount); // 2
} catch (error) {
  if (error.message.includes('Maximum retry attempts')) {
    console.error('Max retries exceeded');
  }
}

Batch Management

getBatches(options)

List all batches with your project records.

const batches = await anchora.getBatches({
  status: 'ANCHORED',    // Filter by status: PENDING, ANCHORED, FAILED
  startDate: '2025-12-01T00:00:00Z',
  limit: 20,
  offset: 0,
  sortBy: 'createdAt',
  sortOrder: 'desc'      // asc or desc
});

console.log('Total batches:', batches.pagination.total);
console.log('Summary:', batches.summary);
// { PENDING: 2, ANCHORED: 20, FAILED: 3, totalRecords: 1250 }

batches.data.forEach(batch => {
  console.log(`Batch ${batch.batchId}: ${batch.projectRecordCount} records`);
  console.log('Sample records:', batch.sampleRecords.slice(0, 3));
});

getBatchDetails(batchId)

Get detailed batch information with all your project records.

const details = await anchora.getBatchDetails(12345);

console.log('Batch:', details.batch);
// {
//   batchId: 12345,
//   merkleRoot: '0xabc...',
//   recordCount: 50,
//   blockNumber: 1234567,
//   status: 'ANCHORED'
// }

console.log('Your records:', details.records.length);
console.log('Stats:', details.stats);
// {
//   total: 10,
//   byStatus: { ANCHORED: 10 },
//   byCollection: { orders: 5, invoices: 5 },
//   encrypted: 7,
//   hashOnly: 2,
//   withWebhooks: 8
// }

Analytics

getAnalytics(options)

Get comprehensive usage analytics and metrics.

const analytics = await anchora.getAnalytics({
  startDate: '2025-11-25T00:00:00Z',
  endDate: '2025-12-25T23:59:59Z',
  granularity: 'day'  // hour, day, week, month
});

// Overview
console.log('Total records:', analytics.data.overview.totalRecords);
console.log('Total batches:', analytics.data.overview.totalBatches);
console.log('Success rate:', analytics.data.overview.successRate + '%');

// Records by status
console.log('Records:', analytics.data.records);
// {
//   total: 5000,
//   byStatus: { queued: 50, batching: 25, anchored: 4900, failed: 25 }
// }

// Webhook statistics
console.log('Webhooks:', analytics.data.webhooks);
// {
//   total: 3000,
//   byStatus: { pending: 100, sent: 2800, failed: 100 },
//   successRate: 93.3,
//   avgRetries: 1
// }

// Encryption statistics
console.log('Encryption rate:', analytics.data.encryption.encryptionRate + '%');

// Time series data
analytics.data.timeSeries.forEach(point => {
  console.log(`${point.date}: ${point.records} records, ${point.anchored} anchored`);
});

// Top collections
analytics.data.collections.forEach(col => {
  console.log(`${col.name}: ${col.count} records (${col.encryptionRate}% encrypted)`);
});

// API usage
console.log('API requests:', analytics.data.apiUsage.summary.totalRequests);
console.log('Avg response time:', analytics.data.apiUsage.summary.avgResponseTime + 'ms');

getAnalyticsSummary()

Get quick analytics summary.

const summary = await anchora.getAnalyticsSummary();

console.log('Total records:', summary.totalRecords);
console.log('Total batches:', summary.totalBatches);
console.log('Recent activity:', summary.recentActivity.slice(0, 5));

Utility Methods

computeHash(data)

Compute SHA-256 hash of data.

const hash = anchora.computeHash({ orderId: 'ORD-123' });
// Returns: '3a7bd3e2360a3d29eea436fcfb7e44c735d117c42d1c1835420b6b9942dd4f1b'

verifyHash(data, expectedHash)

Verify data matches expected hash.

const isValid = anchora.verifyHash(
  { orderId: 'ORD-123' },
  '3a7bd3e2...'
);
// Returns: true or false

Encryption Methods

Anchora SDK provides industrial-grade encryption using PBKDF2 + AES-256-GCM.

📖 Complete Encryption Guide - See detailed documentation

Quick Start: Server-Side Encryption

// Anchor with encryption (Anchora API encrypts server-side)
const result = await anchora.anchor(
  { ssn: '123-45-6789', name: 'John Doe' },
  {
    encrypt: true,
    encryptionKey: 'super-secure-key-32-chars-minimum-here'
  }
);

console.log('Encrypted:', result.encrypted); // true
console.log('Algorithm:', result.encryptionAlgorithm); // AES-256-GCM-PBKDF2

encrypt(data, encryptionKey)

Encrypt data locally with PBKDF2 + AES-256-GCM.

const encrypted = await anchora.encrypt(
  { ssn: '123-45-6789' },
  'super-secure-key-32-chars-minimum-here'
);

// Returns:
// {
//   encrypted: 'a3f2b1c4...',
//   iv: 'f28d7b7e...',
//   authTag: 'c3622a33...',
//   salt: '990fd768...',
//   iterations: 100000,
//   algorithm: 'AES-256-GCM-PBKDF2'
// }

decrypt(encryptedData, encryptionKey, iv, authTag, salt, iterations)

Decrypt PBKDF2 encrypted data.

const decrypted = await anchora.decrypt(
  encrypted.encrypted,
  'super-secure-key-32-chars-minimum-here',
  encrypted.iv,
  encrypted.authTag,
  encrypted.salt,
  encrypted.iterations
);

generateEncryptionKey(length)

Generate a cryptographically secure random key.

const key = anchora.generateEncryptionKey(32);
// Returns: 'aB3$xY9@kL2#...' (32 characters)

validateEncryptionKey(encryptionKey)

Validate encryption key meets security requirements (32 char minimum).

try {
  anchora.validateEncryptionKey('short'); // Throws error
} catch (error) {
  console.error(error.message);
  // 'Encryption key must be at least 32 characters for security'
}

Advanced Methods

anchorWithEncryption(data, encryptionKey, options)

Anchor data with server-side encryption (convenience method).

const result = await anchora.anchorWithEncryption(
  { sensitiveData: 'secret' },
  'super-secure-key-32-chars-minimum-here',
  { metadata: { type: 'sensitive' } }
);

// Equivalent to:
// await anchora.anchor(data, { encrypt: true, encryptionKey: key })

// Returns:
// {
//   success: true,
//   hash: '...',
//   encrypted: true,
//   encryptionAlgorithm: 'AES-256-GCM-PBKDF2',
//   ...
// }

verifyWithDecryption(encryptedData, encryptionKey, iv, authTag, salt, iterations, expectedHash)

Verify and decrypt data, checking for tampering.

const result = await anchora.verifyWithDecryption(
  encrypted.encrypted,
  'super-secure-key-32-chars-minimum-here',
  encrypted.iv,
  encrypted.authTag,
  encrypted.salt,
  encrypted.iterations,
  expectedHash
);

// Returns:
// {
//   verified: true,
//   decryptedData: { ... },
//   tampered: false,
//   ...
// }

Real-World Examples

E-commerce Order Verification

// When order is created
const order = {
  orderId: 'ORD-12345',
  userId: 'user-123',
  total: 999.99,
  items: [...]
};

// Save to your database
await db.orders.insertOne(order);

// Anchor to Anchora
const result = await anchora.anchor(order);

// Store proof in your database
await db.orders.updateOne(
  { orderId: 'ORD-12345' },
  { 
    $set: { 
      anchora_hash: result.hash,
      anchora_timestamp: result.timestamp
    }
  }
);

// Later: Verify order hasn't been tampered with
const order = await db.orders.findOne({ orderId: 'ORD-12345' });
const verification = await anchora.verify(order);

if (!verification.verified) {
  console.error('Order has been tampered with!');
}

Healthcare Records with Encryption

// Store encrypted medical record
const patientData = {
  patientId: 'P-123',
  diagnosis: 'Type 2 Diabetes',
  medication: 'Metformin 500mg'
};

const encryptionKey = anchora.generateEncryptionKey();

// Encrypt and anchor
const result = await anchora.anchorWithEncryption(
  patientData,
  encryptionKey,
  { metadata: { type: 'medical_record' } }
);

// Store in database
await db.patients.insertOne({
  patientId: 'P-123',
  encryptedData: result.encryptedData,
  anchora_hash: result.hash,
  encryptionKey: encryptionKey // Store securely!
});

// Later: Retrieve and verify
const record = await db.patients.findOne({ patientId: 'P-123' });

const verification = await anchora.verifyWithDecryption(
  record.encryptedData,
  record.encryptionKey,
  record.anchora_hash
);

if (verification.tampered) {
  console.error('Medical record has been tampered with!');
} else {
  console.log('Patient data:', verification.decryptedData);
}

Financial Transaction Audit Trail

// Daily batch anchoring
const todayTransactions = await db.transactions.find({
  date: { $gte: startOfDay, $lt: endOfDay }
});

const result = await anchora.anchor({
  date: new Date().toISOString(),
  count: todayTransactions.length,
  totalAmount: todayTransactions.reduce((sum, t) => sum + t.amount, 0),
  transactions: todayTransactions.map(t => t.transactionId)
});

// Store batch proof
await db.auditLog.insertOne({
  date: new Date(),
  type: 'daily_batch',
  anchora_hash: result.hash,
  anchora_proof: result.recordId
});

Error Handling

const { AnchoraClient, ValidationError, AuthenticationError } = require('@anchora/sdk');

try {
  const result = await anchora.anchor(data);
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Invalid data:', error.message);
  } else if (error instanceof AuthenticationError) {
    console.error('Authentication failed:', error.message);
  } else {
    console.error('Unexpected error:', error);
  }
}

Error Types

  • ValidationError - Invalid input data
  • AuthenticationError - API key invalid or expired
  • NetworkError - Network connectivity issues
  • VerificationError - Data verification failed
  • AnchoraError - General Anchora error

Best Practices

  1. Store Hashes, Not Data - Only store the hash and proof in your database
  2. Use Encryption - Encrypt sensitive data before storing
  3. Verify on Read - Always verify data integrity when reading critical records
  4. Batch Operations - Anchor multiple records together for efficiency
  5. Handle Errors - Implement proper error handling for all operations
  6. Secure Keys - Store encryption keys and API keys securely

Support & Links

  • Website: https://www.anchora.co.in
  • GitHub (this repo): https://github.com/anchora-labs/anchora-sdk-js
  • npm: https://www.npmjs.com/package/@anchora/sdk
  • Issues / bug reports: https://github.com/anchora-labs/anchora-sdk-js/issues
  • Email: [email protected]

Contributing

PRs welcome — please open an issue first to discuss the change. Bug reports and security disclosures appreciated; for security issues, please email rather than filing a public issue.

License

MIT — see LICENSE for details.