@flowhash/nftc-client
v0.1.0
Published
TypeScript client SDK for NFTC Protocol Registry API
Downloads
10
Maintainers
Readme
NFTC Protocol Client SDK
A comprehensive TypeScript client SDK for the NFTC Protocol Registry API. Provides type-safe, promise-based access to credential issuance, verification, settlement, and GDPR operations.
Features
- Full API Coverage: Complete implementation of all NFTC Registry endpoints
- Type-Safe: 100% TypeScript with full type definitions
- Error Handling: Custom error classes for different failure scenarios
- Request Retry Logic: Automatic retries with exponential backoff
- Token Management: Built-in JWT authentication and token refresh
- Correlation Tracking: Request tracking across distributed systems
- Interceptors: Request/response interceptors for logging and preprocessing
- Browser Compatible: Works in both Node.js and browser environments
- Zero Dependencies: Only requires axios for HTTP requests
Installation
npm install @flowhash/nftc-client axiosOr with yarn:
yarn add @flowhash/nftc-client axiosQuick Start
Basic Initialization
import { NFTCClient } from '@flowhash/nftc-client';
const client = new NFTCClient({
baseURL: 'https://api.nftcprotocol.org',
apiKey: 'your-api-key',
timeout: 30000,
retryAttempts: 3
});Issue a Right-to-Use Credential
const rtu = await client.credentials.issueRTU({
holderDid: 'did:example:user123',
resourceId: 'asset:forklift:FL-001',
resourceType: 'equipment',
validFrom: '2024-01-01T00:00:00Z',
validUntil: '2024-12-31T23:59:59Z',
usagePolicy: {
maxHours: 160,
geofence: {
type: 'circle',
coordinates: [40.7128, -74.0060],
radius: 5
}
}
});
console.log('RTU issued:', rtu.id);Record Proof-of-Use
const pou = await client.credentials.issueProofOfUse({
holderDid: 'did:example:user123',
rtuReference: rtu.id,
resourceId: 'asset:forklift:FL-001',
startTime: '2024-01-15T08:00:00Z',
endTime: '2024-01-15T16:00:00Z',
metering: {
hoursUsed: 8,
distanceTraveled: 45.5,
fuelConsumed: 12.3
}
});
console.log('Usage recorded:', pou.id);Verify a Credential
const result = await client.verify.verifyCredential(rtu.id);
if (result.valid) {
console.log('Credential is valid');
console.log('Signature valid:', result.checks.signatureValid);
console.log('Schema valid:', result.checks.schemaValid);
} else {
console.log('Verification failed:', result.errors);
}Record Contributions and Settle
// Record a contribution
const contribution = await client.settlement.recordContribution({
contributorDid: 'did:example:worker123',
contributionType: 'labor',
projectId: 'project:renovation:2024',
valueUnits: 40,
valueMetric: 'hours',
period: {
start: '2024-01-01T00:00:00Z',
end: '2024-01-31T23:59:59Z'
},
description: 'Electrical installation work'
});
// Close settlement
const receipt = await client.settlement.closeSettlement({
participantDid: 'did:example:worker123',
settlementId: 'settlement:proj2024:q1',
contributions: [contribution.id],
totalValue: 3000,
currency: 'USD',
breakdown: [{
contributionId: contribution.id,
valueUnits: 40,
valueMetric: 'hours',
rate: 75,
compensationAmount: 3000
}],
paymentMethod: 'bank_transfer'
});
console.log('Settlement closed:', receipt.settlementId);Authentication
Challenge-Response Authentication
import { signData } from '@flowhash/nftc-core';
// Get challenge
const challenge = await client.auth.getAuthChallenge(did);
// Sign challenge with your private key
const signature = await signData(challenge.challenge, privateKey);
// Login
const token = await client.auth.login(did, signature);
// Set token for subsequent requests
client.setAuthToken(token.accessToken);
// Setup automatic token refresh
client.setRefreshTokenFunction(async (refreshToken) => {
const newToken = await client.auth.refreshToken(refreshToken);
return newToken.accessToken;
});Validate and Revoke Tokens
// Check if token is valid
const validation = await client.auth.validateToken(token);
console.log('Token valid:', validation.valid);
// Revoke token
await client.auth.revokeToken(token);
// Logout session
await client.auth.logout(did);Credential Management
List Credentials
// Get paginated list of credentials for a holder
const page = await client.credentials.listCredentials(
'did:example:user123',
limit: 50,
offset: 0
);
console.log('Total credentials:', page.total);
console.log('Retrieved:', page.credentials.length);
// Process paginated results
for (let offset = 0; offset < page.total; offset += 50) {
const page = await client.credentials.listCredentials(
did,
50,
offset
);
// Process page
}Get Specific Credential
const credential = await client.credentials.getCredential('did:nftc:rtu:xyz123');
console.log('Holder:', credential.credentialSubject.id);
console.log('Resource:', credential.credentialSubject.resourceId);Revoke Credential
const result = await client.credentials.revokeCredential(
'did:nftc:rtu:xyz123',
'No longer needed'
);
console.log('Revoked at:', result.revokedAt);Export Credentials
const exported = await client.credentials.exportCredentials(
'did:example:user123',
format: 'json-ld'
);
console.log('Exported credentials:', exported.credentials.length);Verification Operations
Comprehensive Verification
const result = await client.verify.verifyCredential(credentialId);
console.log('Overall valid:', result.valid);
console.log('Checks:');
console.log(' - Signature:', result.checks.signatureValid);
console.log(' - Inclusion proof:', result.checks.inclusionProofValid);
console.log(' - Temporal:', result.checks.temporallyValid);
console.log(' - Schema:', result.checks.schemaValid);
console.log(' - Invariants:', result.checks.invariantsValid);Specific Verification Checks
// Verify signature
const sig = await client.verify.verifySignature(credentialId);
console.log('Signature valid:', sig.signatureValid);
// Check temporal validity
const temporal = await client.verify.checkTemporalValidity(credentialId);
console.log('Currently valid:', temporal.isCurrentlyValid);
// Verify inclusion proof
const inclusion = await client.verify.verifyInclusionProof(credentialId);
console.log('Anchor valid:', inclusion.inclusionProofValid);
// Check schema compliance
const schema = await client.verify.verifySchemaCompliance(credentialId);
console.log('Schema compliant:', schema.compliant);
// Verify invariants
const invariants = await client.verify.verifyInvariants(credentialId);
console.log('Invariants valid:', invariants.invariantsValid);Batch Verification
const credentialIds = [
'did:nftc:rtu:123',
'did:nftc:poc:456',
'did:nftc:settlement:789'
];
const results = await client.verify.verifyCredentialsInBatch(credentialIds);
results.forEach((result, index) => {
console.log(`Credential ${index + 1}:`, result.valid ? 'valid' : 'invalid');
});Get Verification Status
const status = await client.verify.getVerificationStatus(credentialId);
console.log('Status:', status.status); // 'valid', 'invalid', 'revoked', 'expired', 'pending'
console.log('Last verified:', status.lastVerified);Settlement Management
Record Contributions
// Labor contribution
const labor = await client.settlement.recordContribution({
contributorDid: 'did:example:worker123',
contributionType: 'labor',
projectId: 'project:renovation:2024',
valueUnits: 40,
valueMetric: 'hours',
period: '2024-01-01T00:00:00Z/2024-01-31T23:59:59Z',
description: 'Electrical work'
});
// Material contribution
const materials = await client.settlement.recordContribution({
contributorDid: 'did:example:supplier456',
contributionType: 'resource',
projectId: 'project:renovation:2024',
valueUnits: 5000,
valueMetric: 'units',
period: {
start: '2024-01-01T00:00:00Z',
end: '2024-01-31T23:59:59Z'
},
description: 'Electrical materials'
});
// Equipment contribution
const equipment = await client.settlement.recordContribution({
contributorDid: 'did:example:equipment-owner',
contributionType: 'equipment',
projectId: 'project:renovation:2024',
valueUnits: 10,
valueMetric: 'days',
period: {
start: '2024-01-01T00:00:00Z',
end: '2024-01-31T23:59:59Z'
}
});List Contributions
const contributions = await client.settlement.listContributions(
'project:renovation:2024',
limit: 50,
offset: 0
);
console.log('Total contributions:', contributions.total);
contributions.contributions.forEach(contrib => {
console.log(`${contrib.credentialSubject.contributionType}: ${contrib.credentialSubject.valueUnits} ${contrib.credentialSubject.valueMetric}`);
});Close Settlement
const settlement = await client.settlement.closeSettlement({
participantDid: 'did:example:worker123',
settlementId: 'settlement:proj2024:q1',
contributions: [labor.id, equipment.id],
totalValue: 3750,
currency: 'USD',
breakdown: [
{
contributionId: labor.id,
valueUnits: 40,
valueMetric: 'hours',
rate: 75,
compensationAmount: 3000
},
{
contributionId: equipment.id,
valueUnits: 10,
valueMetric: 'days',
rate: 75,
compensationAmount: 750
}
],
paymentMethod: 'bank_transfer',
paymentReference: 'txn:wire:2024-01-31'
});
console.log('Settlement closed');
console.log('Total compensation:', settlement.totalValue, settlement.currency);Get Settlement Summary
const summary = await client.settlement.getSettlementSummary(
'did:example:org123',
'2024-01-01T00:00:00Z',
'2024-01-31T23:59:59Z'
);
console.log('Q1 2024 Summary:');
console.log(' Total settlements:', summary.totalSettlements);
console.log(' Total contributions:', summary.totalContributions);
console.log(' Total compensation:', summary.totalCompensation, summary.currency);GDPR Operations
Export Personal Data
// Full export
const data = await client.gdpr.exportData('did:example:user123', 'json');
console.log('Credentials:', data.credentials.length);
console.log('Transactions:', data.transactions.length);
// Export specific credential types
const rtuOnly = await client.gdpr.exportCredentialsByType(
'did:example:user123',
['RightToUse']
);
// Export date range
const january = await client.gdpr.exportCredentialsByDateRange(
'did:example:user123',
'2024-01-01T00:00:00Z',
'2024-01-31T23:59:59Z'
);Check GDPR Status
const status = await client.gdpr.getGDPRStatus('did:example:user123');
console.log('Data held:', status.dataHeld);
console.log('Credentials:', status.credentialCount);
console.log('Last export:', status.lastExportDate);Delete Personal Data
// Step 1: Request deletion token
const tokenResponse = await client.gdpr.requestDataDeletionToken('did:example:user123');
console.log('Token received, expires in', tokenResponse.expirationHours, 'hours');
// Step 2: Delete with confirmation (IRREVERSIBLE!)
const result = await client.gdpr.deleteData('did:example:user123', tokenResponse.token);
console.log('Data deleted at:', result.deletedAt);Manage Deletion Requests
// List deletion requests
const requests = await client.gdpr.listDeletionRequests('did:example:user123');
requests.forEach(req => {
console.log(`${req.id}: ${req.status}`);
});
// Cancel a deletion request
const cancelled = await client.gdpr.cancelDeletionRequest(
'did:example:user123',
'req_123'
);
console.log('Cancelled at:', cancelled.cancelledAt);Error Handling
Catch Specific Errors
import {
ValidationError,
AuthenticationError,
NetworkError,
NotFoundError,
isNFTCError
} from '@flowhash/nftc-client';
try {
await client.verify.verifyCredential('did:nftc:rtu:xyz123');
} catch (error) {
if (error instanceof ValidationError) {
console.error('Invalid request:', error.message);
} else if (error instanceof AuthenticationError) {
console.error('Authentication failed');
} else if (error instanceof NetworkError) {
console.error('Network error:', error.message);
console.error('Retry count:', error.retryCount);
} else if (error instanceof NotFoundError) {
console.error('Credential not found');
} else if (isNFTCError(error)) {
console.error('NFTC error:', error.code, error.message);
} else {
console.error('Unknown error:', error);
}
}Available Error Classes
NFTCError- Base error classValidationError- Request validation failedAuthenticationError- Authentication failed (401)AuthorizationError- Insufficient permissions (403)NetworkError- Network request failedNotFoundError- Resource not found (404)ConflictError- Request conflict (409)RateLimitError- Rate limit exceeded (429)ServerError- Server error (5xx)TimeoutError- Request timeoutParseError- Response parsing failed
Advanced Features
Correlation ID Tracking
// Set correlation ID for request tracing
client.setCorrelationId('trace-12345');
// Get current correlation ID
const traceId = client.getCorrelationId();
console.log('Tracing as:', traceId);
// All requests will include:
// X-Correlation-ID: trace-12345Custom Headers
const client = new NFTCClient({
baseURL: 'https://api.nftcprotocol.org',
headers: {
'X-Custom-Header': 'custom-value',
'X-API-Version': 'v1'
}
});Request Configuration
const client = new NFTCClient({
baseURL: 'https://api.nftcprotocol.org',
timeout: 30000, // 30 second timeout
retryAttempts: 3, // Retry failed requests 3 times
retryDelay: 1000 // 1 second initial retry delay (exponential backoff)
});API Reference
Credentials Endpoint (client.credentials.*)
issueRTU(params)- Issue Right-to-Use credentialissueProofOfUse(params)- Record Proof-of-Use credentialgetCredential(id)- Get credential by IDlistCredentials(did, limit, offset)- List holder's credentialsrevokeCredential(id, reason)- Revoke credentialexportCredentials(did, format)- Export credentials
Settlement Endpoint (client.settlement.*)
recordContribution(params)- Record Proof-of-ContributiongetContribution(id)- Get contribution by IDlistContributions(projectId, limit, offset)- List project contributionscloseSettlement(params)- Close settlement and issue receiptgetSettlement(id)- Get settlement by IDlistSettlements(did, limit, offset)- List participant's settlementsgetSettlementSummary(did, start, end)- Get settlement summary
Verification Endpoint (client.verify.*)
verifyCredential(id)- Comprehensive credential verificationverifyCredentialData(credential)- Verify credential objectverifyCredentialsInBatch(ids)- Batch verificationverifySignature(id)- Verify signature onlyverifyInclusionProof(id)- Verify Flowhash anchorcheckTemporalValidity(id)- Check validity periodsverifySchemaCompliance(id)- Verify JSON schemaverifyInvariants(id)- Verify protocol invariantsgetVerificationStatus(id)- Get verification status
GDPR Endpoint (client.gdpr.*)
exportData(did, format)- Export all personal dataexportCredentialsByType(did, types)- Export filtered by typeexportCredentialsByDateRange(did, start, end)- Export by date rangedeleteData(did, token)- Delete all personal datarequestDataDeletionToken(did)- Get deletion confirmation tokengetGDPRStatus(did)- Get GDPR compliance statuslistDeletionRequests(did)- List deletion requestscancelDeletionRequest(did, requestId)- Cancel pending deletion
Authentication Endpoint (client.auth.*)
login(did, signature)- Authenticate with signaturegetAuthChallenge(did)- Get challenge for signingrefreshToken(token)- Refresh access tokenvalidateToken(token)- Check token validityrevokeToken(token)- Revoke tokenlogout(did)- Logout sessiongetAuthStatus(token)- Get auth statusregisterDID(did, document)- Register new DIDisDIDRegistered(did)- Check registration status
Browser Support
This SDK works in modern browsers with ES2020+ support. For older browsers, use a transpiler like Babel.
<script src="https://unpkg.com/@flowhash/nftc-client"></script>
<script>
const client = new NFTC.NFTCClient({
baseURL: 'https://api.nftcprotocol.org'
});
</script>TypeScript Support
Full TypeScript support with type definitions included:
import {
NFTCClient,
RightToUseCredential,
VerificationResult,
IssueRTUParams
} from '@flowhash/nftc-client';
// All types are exported for use in your code
const params: IssueRTUParams = { /* ... */ };
const credential: RightToUseCredential = await client.credentials.issueRTU(params);
const result: VerificationResult = await client.verify.verifyCredential(credential.id);Examples
See /examples/basic-usage.ts for comprehensive examples covering:
- Client initialization
- Authentication workflows
- Issuing credentials
- Recording proof-of-use
- Managing contributions and settlements
- Verifying credentials
- GDPR operations
- Error handling
- Pagination
- Correlation tracking
Contributing
Contributions are welcome! Please ensure:
- All code is TypeScript with strict mode enabled
- Full JSDoc documentation on public APIs
- Comprehensive error handling
- 100% type coverage
License
Apache 2.0 - See LICENSE file
Support
For issues and feature requests, visit: https://github.com/nftc-protocol/nftc-client/issues
