defarm-sdk
Version:
DeFarm SDK - On-premise blockchain data processing and tokenization engine for agriculture supply chain
449 lines (391 loc) • 12.4 kB
text/typescript
import type { Asset } from '../types';
import { EventEmitter } from 'events';
import { DeFarmSDKError, ErrorCode } from '../utils';
export interface PremiumAPIConfig {
baseUrl: string;
apiKey: string;
timeout?: number;
retries?: number;
version?: string;
}
export interface QualityScore {
overall: number;
factors: {
completeness: number;
accuracy: number;
consistency: number;
freshness: number;
};
recommendations: string[];
}
export interface FraudDetection {
riskScore: number;
alerts: Array<{
type: 'data_inconsistency' | 'unusual_pattern' | 'duplicate_detected' | 'temporal_anomaly';
severity: 'low' | 'medium' | 'high' | 'critical';
message: string;
evidence: any;
}>;
confidence: number;
}
export interface ComplianceCheck {
passed: boolean;
checks: Array<{
rule: string;
status: 'pass' | 'fail' | 'warning';
message: string;
regulation: string;
}>;
certifications: string[];
}
export interface MarketIntelligence {
pricing: {
current: number;
currency: string;
trend: 'up' | 'down' | 'stable';
confidence: number;
};
demand: {
level: 'low' | 'medium' | 'high' | 'very_high';
forecast: number[];
factors: string[];
};
competition: {
suppliers: number;
marketShare: number;
competitive_advantage: string[];
};
}
export interface RiskAssessment {
overall: number;
categories: {
operational: number;
financial: number;
regulatory: number;
environmental: number;
market: number;
};
recommendations: Array<{
category: string;
priority: 'low' | 'medium' | 'high' | 'critical';
action: string;
impact: string;
}>;
}
export class PremiumAPIClient extends EventEmitter {
private config: PremiumAPIConfig;
private rateLimitRemaining: number = 1000;
private rateLimitReset: Date = new Date();
constructor(config: PremiumAPIConfig) {
super();
this.config = {
timeout: 30000,
retries: 3,
version: 'v1',
...config
};
}
async calculateQualityScore(asset: Asset): Promise<QualityScore> {
return this.makeRequest('/analytics/quality-score', {
method: 'POST',
body: JSON.stringify({ asset }),
headers: { 'Content-Type': 'application/json' }
});
}
async detectFraud(asset: Asset): Promise<FraudDetection> {
return this.makeRequest('/analytics/fraud-detection', {
method: 'POST',
body: JSON.stringify({ asset }),
headers: { 'Content-Type': 'application/json' }
});
}
async checkCompliance(asset: Asset, regulations: string[] = []): Promise<ComplianceCheck> {
return this.makeRequest('/compliance/check', {
method: 'POST',
body: JSON.stringify({ asset, regulations }),
headers: { 'Content-Type': 'application/json' }
});
}
async getMarketIntelligence(
category: string,
subcategory: string,
location?: { country: string; state?: string }
): Promise<MarketIntelligence> {
const params = new URLSearchParams({
category,
subcategory,
...(location?.country && { country: location.country }),
...(location?.state && { state: location.state })
});
return this.makeRequest(`/market/intelligence?${params.toString()}`);
}
async assessRisk(asset: Asset): Promise<RiskAssessment> {
return this.makeRequest('/analytics/risk-assessment', {
method: 'POST',
body: JSON.stringify({ asset }),
headers: { 'Content-Type': 'application/json' }
});
}
async batchAnalyze(assets: Asset[]): Promise<{
qualityScores: QualityScore[];
fraudDetections: FraudDetection[];
complianceChecks: ComplianceCheck[];
riskAssessments: RiskAssessment[];
}> {
return this.makeRequest('/analytics/batch', {
method: 'POST',
body: JSON.stringify({ assets }),
headers: { 'Content-Type': 'application/json' }
});
}
async getUsageStats(): Promise<{
period: string;
totalCalls: number;
callsByEndpoint: Record<string, number>;
costBreakdown: Record<string, number>;
remainingCredits: number;
}> {
return this.makeRequest('/account/usage');
}
getRateLimitInfo(): { remaining: number; resetAt: Date } {
return {
remaining: this.rateLimitRemaining,
resetAt: this.rateLimitReset
};
}
private async makeRequest(endpoint: string, options: RequestInit = {}): Promise<any> {
// Emit request event
this.emit('request', { endpoint, options });
// Check rate limits before making request
if (this.rateLimitRemaining <= 0 && this.rateLimitReset > new Date()) {
const waitTime = this.rateLimitReset.getTime() - Date.now();
throw new DeFarmSDKError(
ErrorCode.RATE_LIMIT_EXCEEDED,
`Rate limit exceeded. Retry after ${Math.ceil(waitTime / 1000)} seconds`,
{ retryAfter: this.rateLimitReset }
);
}
const url = `${this.config.baseUrl}/${this.config.version}${endpoint}`;
const requestOptions: RequestInit = {
...options,
headers: {
'Authorization': `Bearer ${this.config.apiKey}`,
'User-Agent': 'DeFarm-SDK/0.1.0',
...options.headers
}
};
let lastError: Error | null = null;
for (let attempt = 0; attempt <= (this.config.retries || 3); attempt++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
const response = await fetch(url, {
...requestOptions,
signal: controller.signal
});
clearTimeout(timeoutId);
this.updateRateLimitInfo(response);
if (!response.ok) {
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000;
if (attempt < (this.config.retries || 3)) {
await this.delay(waitTime);
continue;
}
}
const errorData = await response.json().catch(() => ({}));
const errorCode = response.status === 401 ? ErrorCode.AUTHENTICATION_ERROR :
response.status === 403 ? ErrorCode.AUTHORIZATION_ERROR :
response.status === 429 ? ErrorCode.RATE_LIMIT_EXCEEDED :
response.status >= 500 ? ErrorCode.API_ERROR :
ErrorCode.PREMIUM_API_ERROR;
throw new DeFarmSDKError(
errorCode,
`API request failed: ${response.status} ${response.statusText}. ${
errorData.message || errorData.error || ''
}`,
{ status: response.status, endpoint, errorData }
);
}
const data = await response.json();
// Emit success event
this.emit('response', { endpoint, status: response.status, data });
return data;
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (error instanceof Error && error.name === 'AbortError') {
lastError = new DeFarmSDKError(
ErrorCode.TIMEOUT_ERROR,
`Request timeout after ${this.config.timeout}ms`,
{ endpoint, timeout: this.config.timeout }
);
}
// Emit error event
this.emit('error', { endpoint, error: lastError, attempt });
if (attempt < (this.config.retries || 3)) {
const backoffTime = Math.pow(2, attempt) * 1000;
await this.delay(backoffTime);
continue;
}
}
}
throw lastError || new Error('Unknown API error');
}
private updateRateLimitInfo(response: Response): void {
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
if (remaining) {
this.rateLimitRemaining = parseInt(remaining);
}
if (reset) {
this.rateLimitReset = new Date(parseInt(reset) * 1000);
}
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Monitoring and debugging methods
async healthCheck(): Promise<{
status: 'healthy' | 'degraded' | 'unhealthy';
latency: number;
rateLimits: { remaining: number; resetAt: Date };
version: string;
}> {
const start = Date.now();
try {
const response = await this.makeRequest('/health');
const latency = Date.now() - start;
return {
status: 'healthy',
latency,
rateLimits: this.getRateLimitInfo(),
version: response.version || this.config.version || 'unknown'
};
} catch (error) {
return {
status: 'unhealthy',
latency: Date.now() - start,
rateLimits: this.getRateLimitInfo(),
version: this.config.version || 'unknown'
};
}
}
// Enhanced analytics methods
async getAnalyticsReport(
assets: Asset[],
options: {
includeQuality?: boolean;
includeFraud?: boolean;
includeCompliance?: boolean;
includeRisk?: boolean;
includeMarket?: boolean;
} = {}
): Promise<{
summary: {
totalAssets: number;
averageQualityScore?: number;
highRiskCount?: number;
complianceRate?: number;
};
details: {
byCategory: Record<string, any>;
byLocation: Record<string, any>;
trends: any[];
};
recommendations: string[];
}> {
const payload = { assets, options };
return this.makeRequest('/analytics/report', {
method: 'POST',
body: JSON.stringify(payload),
headers: { 'Content-Type': 'application/json' }
});
}
// Data enrichment methods
async enrichAsset(asset: Asset): Promise<{
enriched: Asset;
sources: string[];
confidence: number;
additions: Record<string, any>;
}> {
return this.makeRequest('/enrich/asset', {
method: 'POST',
body: JSON.stringify({ asset }),
headers: { 'Content-Type': 'application/json' }
});
}
// Predictive analytics
async predictPrice(
asset: Asset,
timeframe: '1d' | '1w' | '1m' | '3m' | '6m' | '1y'
): Promise<{
current: number;
predicted: number;
confidence: number;
factors: Array<{ name: string; impact: number }>;
range: { low: number; high: number };
}> {
return this.makeRequest('/predict/price', {
method: 'POST',
body: JSON.stringify({ asset, timeframe }),
headers: { 'Content-Type': 'application/json' }
});
}
// Blockchain verification
async verifyOnChain(
dfid: string,
blockchain: 'stellar' | 'polygon' | 'ethereum' = 'stellar'
): Promise<{
verified: boolean;
transactionHash?: string;
blockNumber?: number;
timestamp?: Date;
data?: any;
}> {
return this.makeRequest(`/verify/blockchain/${blockchain}/${dfid}`);
}
// Compliance automation
async generateComplianceReport(
assets: Asset[],
regulations: string[],
format: 'pdf' | 'json' | 'csv' = 'json'
): Promise<{
reportId: string;
status: 'completed' | 'processing' | 'failed';
downloadUrl?: string;
expiresAt?: Date;
}> {
return this.makeRequest('/compliance/report/generate', {
method: 'POST',
body: JSON.stringify({ assets, regulations, format }),
headers: { 'Content-Type': 'application/json' }
});
}
// Real-time monitoring
async subscribeToAlerts(
criteria: {
categories?: string[];
riskThreshold?: number;
complianceRules?: string[];
priceChanges?: { threshold: number; direction: 'up' | 'down' | 'both' };
},
webhook?: string
): Promise<{
subscriptionId: string;
active: boolean;
criteria: any;
webhookUrl?: string;
}> {
return this.makeRequest('/alerts/subscribe', {
method: 'POST',
body: JSON.stringify({ criteria, webhook }),
headers: { 'Content-Type': 'application/json' }
});
}
async unsubscribe(subscriptionId: string): Promise<{ success: boolean }> {
return this.makeRequest(`/alerts/unsubscribe/${subscriptionId}`, {
method: 'DELETE'
});
}
}