import { PinataSDK } from 'pinata'; export class IpfsService { private pinata: PinataSDK | null; private gatewayUrl: string; constructor() { const pinataJwt = process.env.PINATA_JWT || ''; const gatewayUrl = process.env.GATEWAY_URL || ''; if (!pinataJwt) { console.warn('PINATA_JWT not set - IPFS features will be disabled'); this.pinata = null; this.gatewayUrl = ''; } else { const gatewayDomain = gatewayUrl ? gatewayUrl.replace(/^https?:\/\//, '').replace(/\/ipfs\/?$/, '') : 'gateway.pinata.cloud'; this.gatewayUrl = `https://${gatewayDomain}/ipfs/`; if (!gatewayUrl) { console.warn('GATEWAY_URL not set - using default Pinata gateway'); } this.pinata = new PinataSDK({ pinataJwt: pinataJwt, pinataGateway: gatewayDomain, }); } } async uploadMetadata(metadata: { name: string; description: string; endpoint: string; price: number; creatorId: string; category?: string; capabilities?: string[]; metadata?: Record; }): Promise { if (!this.pinata) { throw new Error('Pinata JWT not configured'); } try { // Convert metadata object to JSON string for upload const jsonString = JSON.stringify(metadata); const file = new File( [jsonString], `agent-${metadata.name}-${Date.now()}.json`, { type: 'application/json' } ); const upload = await this.pinata.upload.public.file(file); // Return the CID (IPFS hash) return upload.cid; } catch (error) { console.error('IPFS upload error:', error); throw new Error('Failed to upload metadata to IPFS'); } } /** * Get metadata from IPFS hash (CID) */ async getMetadata(cid: string): Promise { if (!this.pinata) { throw new Error('Pinata JWT not configured'); } try { const data = await this.pinata.gateways.public.get(cid); return data; } catch (error) { console.error('IPFS fetch error:', error); throw new Error('Failed to fetch metadata from IPFS'); } } /** * Upload file to IPFS */ async uploadFile(file: File): Promise<{ cid: string; size: number }> { if (!this.pinata) { throw new Error('Pinata JWT not configured'); } try { const upload = await this.pinata.upload.public.file(file); return { cid: upload.cid, size: upload.size || file.size, }; } catch (error) { console.error('IPFS file upload error:', error); throw new Error('Failed to upload file to IPFS'); } } /** * Get gateway URL for IPFS hash (CID) * Uses the configured gateway to construct the URL */ getGatewayUrl(cid: string): string { if (this.gatewayUrl) { // Remove trailing slash if present, add CID const base = this.gatewayUrl.endsWith('/') ? this.gatewayUrl.slice(0, -1) : this.gatewayUrl; return `${base}/${cid}`; } // Fallback to default gateway return `https://gateway.pinata.cloud/ipfs/${cid}`; } }