@verdikta/common
v1.7.0
Published
Shared utilities for Verdikta blockchain integration
Downloads
474
Maintainers
Readme
@verdikta/common
Shared utilities for Verdikta blockchain integration. This package provides common functionality for interacting with the Verdikta decentralized AI arbitration platform.
Overview
Verdikta is a blockchain platform built on Base/ETH designed for decentralized AI-adjudicated judgements. This package contains the core utilities needed to interact with Verdikta arbiters, parse manifests, and handle IPFS operations.
Installation
npm install @verdikta/commonQuick Start
Simple Usage
const { parseManifest, validateRequest } = require('@verdikta/common');
// Parse a manifest from an extracted archive
const result = await parseManifest('/path/to/extracted/archive');
// Validate a request object
await validateRequest(requestObject);Advanced Usage with Configuration
const { createClient } = require('@verdikta/common');
const verdikta = createClient({
ipfs: {
pinningKey: 'your-pinata-api-key',
timeout: 45000
},
logging: {
level: 'debug',
file: true
}
});
const { manifestParser, archiveService, ipfsClient } = verdikta;
// Use the configured services
const archive = await archiveService.getArchive('QmYourCIDHere');
const manifest = await manifestParser.parse('/path/to/archive');Individual Class Usage
const { IPFSClient, ManifestParser, Logger } = require('@verdikta/common');
const logger = new Logger({ level: 'info' });
const ipfsClient = new IPFSClient({
pinningKey: 'your-api-key',
timeout: 30000
}, logger);
const manifestParser = new ManifestParser(ipfsClient, logger);API Reference
Factory Function
createClient(config?)
Creates a configured Verdikta client with all services initialized.
Parameters:
config(optional): Configuration object
Returns: Object with initialized services:
manifestParser: ManifestParser instancearchiveService: ArchiveService instanceipfsClient: IPFSClient instancevalidator: Validator utilitieslogger: Logger instanceconfig: Merged configuration
Core Classes
ManifestParser
Parses Verdikta manifest files and handles multi-CID operations.
Methods:
parse(extractedPath, options?): Parse a single manifest. Optionaloptions.archiveRole('primary'|'bCID') andoptions.cidare attached to content-level errors.parseMultipleManifests(extractedPaths, cidOrder): Parse multiple manifests. Failures on the first CID arearchiveRole: 'primary'; later CIDs arearchiveRole: 'bCID'with that CID.constructCombinedQuery(primaryManifest, bCIDManifests, addendumString?): Combine manifests into a query
Content-level rejections (manifest.json missing/not JSON/schema, primary file missing/not JSON/schema, NUMBER_OF_OUTCOMES mismatch, bCID name mismatch) throw MalformedArchiveError. IPFS fetch failures and I/O errors remain untyped Errors. error.message is unchanged from previous releases.
MalformedArchiveError
const { MalformedArchiveError, ARCHIVE_CHECKS } = require('@verdikta/common');
try {
await manifestParser.parseMultipleManifests(extractedPaths, cidOrder);
} catch (error) {
if (error instanceof MalformedArchiveError) {
// error.archiveRole 'primary' | 'bCID'
// error.cid CID of the failing archive, when known
// error.check stable identifier (see below)
// error.reason human-readable explanation
// error.manifest parsed manifest.json when it could be read
}
throw error;
}check identifiers (ARCHIVE_CHECKS):
| check | When |
| --- | --- |
| manifest-missing | Archive has no manifest.json |
| manifest-not-json | manifest.json is not valid JSON |
| manifest-schema | Manifest fails schema or related business rules |
| primary-missing | primary.filename is not in the archive |
| primary-not-json | Primary file is not valid JSON (e.g. markdown named as primary) |
| primary-schema | Primary JSON is missing query or otherwise invalid |
| outcomes-mismatch | Primary outcomes.length ≠ juryParameters.NUMBER_OF_OUTCOMES |
| bcid-name-mismatch | bCID archive name does not match the primary manifest's bCIDs key |
ArchiveService
Handles archive operations and IPFS integration.
Methods:
getArchive(cid): Fetch archive from IPFS or test fixturesextractArchive(archiveData, extractionPath): Extract archive to filesystem
IPFSClient
Fetches and uploads IPFS content. fetchFromIPFS(cid) walks the gateway list in sweeps: every gateway is tried back to back, and backoff applies only between sweeps. The first 2xx response with a non-empty body wins.
Operator gateways come first. gateways is a list tried in order, or a single URL string treated as a one-item list. The legacy gateway string is one more operator entry, placed after gateways. DEFAULT_IPFS_GATEWAYS is always appended as a fallback:
https://gateway.pinata.cloudhttps://ipfs.iohttps://dweb.link
Entries are trimmed, trailing slashes are removed, duplicates are dropped, and values that are not http: or https: URLs are ignored. gatewayToken is sent as the x-pinata-gateway-token header only to operator-configured gateways.
retryOptions.retries is the number of additional sweeps after the first (default 2, so up to three sweeps). maxFetchMs (default 120000) is the wall-clock budget; once it is spent, no new sweep or gateway request starts. A 429 puts that gateway on cooldown for min(Retry-After, 300) seconds, or 60 seconds when the header is missing or unparsable. A sweep in which every responding gateway returns 400 or 422 fails immediately.
uploadRetryOptions is the backoff for uploadToIPFS and does not follow the fetch sweep schedule. The default is five additional attempts (retries: 5, factor: 2, minTimeout: 1000, maxTimeout: 15000, randomize: true).
Methods:
fetchFromIPFS(cid): Fetch content from IPFS. Rejection messages start withFailed to fetch from IPFS.uploadToIPFS(filePath): Upload a file to the pinning servicecleanup(): Abort requests still in flight
Logger
Configurable logging with Winston.
Methods:
info(message, meta?): Log info levelerror(message, meta?): Log error levelwarn(message, meta?): Log warning leveldebug(message, meta?): Log debug level
Validation
validator
Provides Joi-based validation for manifests and requests.
Methods:
validateManifest(manifest): Validate manifest structurevalidateRequest(request): Validate request object
Configuration
Default Configuration
{
ipfs: {
gateways: [],
pinningService: 'https://api.pinata.cloud',
pinningKey: process.env.IPFS_PINNING_KEY || '',
timeout: 30000,
maxFetchMs: 120000,
retryOptions: {
retries: 2, // additional fetch sweeps after the first
factor: 2,
minTimeout: 1000,
maxTimeout: 8000,
randomize: true
},
uploadRetryOptions: {
retries: 5,
factor: 2,
minTimeout: 1000,
maxTimeout: 15000,
randomize: true
}
},
logging: {
level: process.env.LOG_LEVEL || 'info',
console: true,
file: false
},
temp: {
dir: process.env.TEMP_DIR || './tmp'
}
}Environment Variables
IPFS_PINNING_KEY: Your IPFS pinning service API keyLOG_LEVEL: Logging level (debug, info, warn, error)TEMP_DIR: Temporary directory for file operations
Testing
Credential-Aware Testing System
This package features an intelligent testing system that adapts based on credential availability:
# Automatic mode detection
npm test
# Check current test mode
npm run test:check
# Force specific modes
npm run test:mocked # No credentials required
npm run test:full # Requires IPFS_PINNING_KEY🎭 Mocked Mode (default without credentials):
- Uses Jest mocks for HTTP calls
- Loads mock files from test fixtures
- Safe for CI/CD environments
- Fast execution
🔑 Full Mode (when IPFS_PINNING_KEY is set):
- Makes real IPFS network calls
- Tests actual retry logic and gateway failover
- Validates real-world performance
- Comprehensive integration testing
Running Tests
npm test # Credential-aware (auto-detects mode)
npm run test:watch # Watch mode
npm run test:coverage # With coverage report
npm run test:modes # Compare both mocked and full modesFor full testing with real IPFS:
export IPFS_PINNING_KEY="your_pinata_api_key"
npm run test:fullSee test/README.md for detailed testing documentation.
Examples
See the examples/ directory for complete usage examples.
Documentation
Additional documentation is available in the docs/ directory:
Contributing
Contributions are welcome! Please follow the existing code style and include tests for new features.
For local development and testing changes before publishing, see the Local Development Guide.
License
MIT License - see LICENSE file for details.
Support
For issues and questions, please use the GitHub issues tracker.
