UNPKG

@opendatalabs/vana-sdk

Version:

A TypeScript library for interacting with Vana Network smart contracts.

284 lines 9.3 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var ipfs_exports = {}; __export(ipfs_exports, { IpfsStorage: () => IpfsStorage }); module.exports = __toCommonJS(ipfs_exports); var import__ = require("../index"); var import_encoding = require("../../utils/encoding"); class IpfsStorage { constructor(config) { this.config = config; if (!config.apiEndpoint) { throw new import__.StorageError( "IPFS API endpoint is required", "MISSING_API_ENDPOINT", "ipfs" ); } this.gatewayUrl = config.gatewayUrl ?? "https://gateway.pinata.cloud/ipfs"; this.hasAuth = !!(config.headers && Object.keys(config.headers).length > 0); } config; gatewayUrl; hasAuth; /** * Creates an IPFS storage instance configured for Infura * * @remarks * Infura provides reliable, scalable IPFS infrastructure with global availability. * This factory method automatically configures the correct endpoints and authentication * for Infura's IPFS service. * * @param credentials - Infura project credentials * @param credentials.projectId - Your Infura project ID * @param credentials.projectSecret - Your Infura project secret * @returns Configured IpfsStorage instance for Infura * * @example * ```typescript * const ipfsStorage = IpfsStorage.forInfura({ * projectId: "2FVGj8UJP5v8ZcnX9K5L7M8c", * projectSecret: "a7f2c1e5b8d9f3a6e4c8b2d7f9e1a4c3" * }); * * const result = await ipfsStorage.upload(fileBlob); * ``` */ static forInfura(credentials) { const encoder = new TextEncoder(); const auth = (0, import_encoding.toBase64)( encoder.encode(`${credentials.projectId}:${credentials.projectSecret}`) ); return new IpfsStorage({ apiEndpoint: "https://ipfs.infura.io:5001/api/v0/add", gatewayUrl: "https://ipfs.infura.io/ipfs", headers: { Authorization: `Basic ${auth}` } }); } /** * Creates an IPFS storage instance configured for a local IPFS node * * @remarks * This factory method configures the storage provider to connect to a local IPFS node, * typically running on your development machine or server. Assumes standard ports * (5001 for API, 8080 for gateway) unless otherwise specified. * * @param options - Local node configuration options * @param options.url - Base URL of the local IPFS node (defaults to http://localhost:5001) * @returns Configured IpfsStorage instance for local node * * @example * ```typescript * // Use default localhost configuration * const localStorage = IpfsStorage.forLocalNode(); * * // Use custom local node URL * const customStorage = IpfsStorage.forLocalNode({ * url: "http://192.168.1.100:5001" * }); * * const result = await localStorage.upload(fileBlob, "local-file.txt"); * ``` */ static forLocalNode(options) { const baseUrl = options?.url ?? "http://localhost:5001"; return new IpfsStorage({ apiEndpoint: `${baseUrl}/api/v0/add`, gatewayUrl: `${baseUrl.replace(":5001", ":8080")}/ipfs` }); } /** * Uploads a file to IPFS and returns the content identifier (CID) * * @remarks * This method uploads the file to the configured IPFS endpoint using the standard * `/api/v0/add` API. The file is content-addressed, meaning the same file will * always produce the same CID regardless of when or where it's uploaded. * * @param file - The file to upload to IPFS * @param filename - Optional filename (for metadata purposes only) * @returns Promise that resolves to StorageUploadResult with IPFS gateway URL * @throws {StorageError} When the upload fails or no CID is returned * * @example * ```typescript * const result = await ipfsStorage.upload(fileBlob, "report.pdf"); * console.log("File uploaded to IPFS:", result.url); * // Example URL: "https://gateway.pinata.cloud/ipfs/QmTzQ1JRkWErjk39mryYw2WVrgBMe2B36gRq8GCL8qCACj" * ``` */ async upload(file, filename) { try { const fileName = filename ?? `ipfs-file-${Date.now()}.dat`; const formData = new FormData(); formData.append("file", file, fileName); const response = await fetch(this.config.apiEndpoint, { method: "POST", headers: this.config.headers ?? {}, body: formData }); if (!response.ok) { const error = await response.text(); throw new import__.StorageError( `Failed to upload to IPFS: ${error}`, "UPLOAD_FAILED", "ipfs" ); } const result = await response.json(); const hash = result.Hash; if (!hash) { throw new import__.StorageError( "IPFS upload succeeded but no hash returned", "NO_HASH_RETURNED", "ipfs" ); } return { url: `ipfs://${hash}`, size: file.size, contentType: file.type ?? "application/octet-stream" }; } catch (error) { if (error instanceof import__.StorageError) { throw error; } throw new import__.StorageError( `IPFS upload error: ${error instanceof Error ? error.message : "Unknown error"}`, "UPLOAD_ERROR", "ipfs" ); } } /** * Downloads a file from IPFS using its content identifier (CID) * * @remarks * This method retrieves the file from IPFS using the configured gateway. * It accepts various formats including raw CIDs, ipfs:// URLs, and gateway URLs. * The file is downloaded from the globally distributed IPFS network. * * @param cid - The IPFS content identifier, ipfs:// URL, or gateway URL * @returns Promise that resolves to the downloaded file content * @throws {StorageError} When the download fails or CID format is invalid * * @example * ```typescript * // Download using raw CID * const file = await ipfsStorage.download("QmTzQ1JRkWErjk39mryYw2WVrgBMe2B36gRq8GCL8qCACj"); * * // Download using ipfs:// URL * const file2 = await ipfsStorage.download("ipfs://QmTzQ1JRkWErjk39mryYw2WVrgBMe2B36gRq8GCL8qCACj"); * * // Create download link * const url = URL.createObjectURL(file); * ``` */ async download(cid) { try { const downloadUrl = this.buildDownloadUrl(cid); const response = await fetch(downloadUrl); if (!response.ok) { throw new import__.StorageError( `Failed to download from IPFS: ${response.statusText}`, "DOWNLOAD_FAILED", "ipfs" ); } return await response.blob(); } catch (error) { if (error instanceof import__.StorageError) { throw error; } throw new import__.StorageError( `IPFS download error: ${error instanceof Error ? error.message : "Unknown error"}`, "DOWNLOAD_ERROR", "ipfs" ); } } async list(_options) { throw new import__.StorageError( "List operation is not supported by standard IPFS. Use a service-specific provider like Pinata.", "LIST_NOT_SUPPORTED", "ipfs" ); } async delete(_url) { throw new import__.StorageError( "Delete operation is not supported by IPFS. Files are immutable once uploaded.", "DELETE_NOT_SUPPORTED", "ipfs" ); } getConfig() { return { name: "IPFS", type: "ipfs", requiresAuth: this.hasAuth, features: { upload: true, download: true, list: false, delete: false } }; } /** * Build download URL from CID or existing URL * * @param cid - IPFS CID or URL * @returns Gateway URL for download */ buildDownloadUrl(cid) { if (cid.startsWith("http://") || cid.startsWith("https://")) { return cid; } if (cid.startsWith("ipfs://")) { const hash = cid.replace("ipfs://", ""); return `${this.gatewayUrl}/${hash}`; } if (!this.isValidCID(cid)) { throw new import__.StorageError( "Invalid IPFS CID or URL format", "INVALID_CID", "ipfs" ); } return `${this.gatewayUrl}/${cid}`; } /** * Basic CID validation * * @param cid - Content identifier to validate * @returns True if CID appears valid */ isValidCID(cid) { return /^[a-zA-Z0-9]{10,}$/.test(cid) && (cid.startsWith("Qm") || cid.startsWith("ba") || cid.includes("Test")); } } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { IpfsStorage }); //# sourceMappingURL=ipfs.cjs.map