Components
All components can be imported and used independently for advanced use cases. The SDK is organized to match the external service structure:
Payments Service
Section titled “Payments Service”Direct interface to the Payments contract for token operations and operator approvals.
import { PaymentsService } from '@filoz/synapse-sdk/payments'import { ethers } from 'ethers'
const provider = new ethers.JsonRpcProvider(rpcUrl)const signer = await provider.getSigner()const paymentsService = new PaymentsService(provider, signer, paymentsAddress, usdfcAddress, false)
// Deposit USDFC to payments contractconst depositTx = await paymentsService.deposit(amount) // amount in base unitsconsole.log(`Deposit transaction: ${depositTx.hash}`)await depositTx.wait() // Wait for confirmation
// Check account infoconst info = await paymentsService.accountInfo() // Uses USDFC by defaultconsole.log('Available funds:', info.availableFunds)
// Approve service as operatorconst approveTx = await paymentsService.approveService( serviceAddress, // e.g., Warm Storage contract address rateAllowance, // per-epoch rate allowance in base units lockupAllowance, // total lockup allowance in base units maxLockupPeriod // max lockup period in epochs (e.g., 86400n for 30 days))console.log(`Service approval transaction: ${approveTx.hash}`)await approveTx.wait() // Wait for confirmation
Service Provider Registry
Section titled “Service Provider Registry”Query and manage service providers registered in the on-chain registry.
import { SPRegistryService } from '@filoz/synapse-sdk/sp-registry'
// Create service instanceconst spRegistry = new SPRegistryService(provider, registryAddress)
// Query providersconst allProviders = await spRegistry.getAllActiveProviders()const provider = await spRegistry.getProvider(providerId)const providerByAddr = await spRegistry.getProviderByAddress(address)
// Check registration statusconst isRegistered = await spRegistry.isRegisteredProvider(address)const providerId = await spRegistry.getProviderIdByAddress(address)const isActive = await spRegistry.isProviderActive(providerId)
// Provider management (requires signer)const registrationInfo = { name: 'My Storage Provider', description: 'Reliable storage service', pdpOffering: { serviceURL: 'https://provider.example.com', minPieceSizeInBytes: 65n, maxPieceSizeInBytes: 34091302912n, storagePricePerTibPerMonth: 5000000000000000000n, location: '/C=US/ST=CA/L=SF', // ... other PDP fields }, capabilities: { hyperCompute: '100x' }}await spRegistry.registerProvider(signer, registrationInfo)await spRegistry.updateProviderInfo(signer, name, description)await spRegistry.removeProvider(signer)
// Product management for PDP servicesawait spRegistry.addPDPProduct(signer, pdpOffering, capabilities)await spRegistry.updatePDPProduct(signer, pdpOffering, capabilities)await spRegistry.deactivateProduct(signer, 0) // 0 = ProductType.PDP
// Query PDP service detailsconst pdpService = await spRegistry.getPDPService(providerId)console.log('Service URL:', pdpService.offering.serviceURL)console.log('Storage Price:', pdpService.offering.storagePricePerTibPerMonth)
Warm Storage Service
Section titled “Warm Storage Service”Interact with the Warm Storage contract for data set management, service provider operations, and storage cost calculations.
import { WarmStorageService } from '@filoz/synapse-sdk/warm-storage'
// Create WarmStorageService using factory methodconst warmStorageService = await WarmStorageService.create(provider, warmStorageAddress)
// Storage cost calculationsconst costs = await warmStorageService.calculateStorageCost(sizeInBytes)console.log(`Storage cost: ${costs.perMonth} per month`)
// Check allowances for storage (returns allowance details and costs)const check = await warmStorageService.checkAllowanceForStorage( sizeInBytes, withCDN, paymentsService // Pass PaymentsService instance)// check.sufficient - boolean indicating if allowances are sufficient// check.costs - storage costs per epoch/day/month
// Prepare storage uploadconst prep = await warmStorageService.prepareStorageUpload({ dataSize: sizeInBytes, withCDN: false}, paymentsService)
// Get client data sets with enhanced detailsconst dataSets = await warmStorageService.getClientDataSetsWithDetails(clientAddress)for (const ds of dataSets) { console.log(`Rail ID: ${ds.railId}, PDP Verifier ID: ${ds.pdpVerifierDataSetId}`) console.log(`Is Live: ${ds.isLive}, Is Managed: ${ds.isManaged}`) console.log(`Next Piece ID: ${ds.nextPieceId}`)}
// Get only data sets managed by this Warm Storage instanceconst managedSets = await warmStorageService.getManagedDataSets(clientAddress)
// Verify data set creationconst verification = await warmStorageService.verifyDataSetCreation(txHash)if (verification.dataSetLive) { console.log(`Data set ${verification.dataSetId} is live!`)}
// Service provider operationsconst isApproved = await warmStorageService.isProviderApproved(providerAddress)const providers = await warmStorageService.getAllApprovedProviders()
Subgraph Service
Section titled “Subgraph Service”The SubgraphService provides access to Synapse-compatible subgraphs for provider discovery, data set tracking, and more.
// Create subgraph serviceconst subgraphService = new SubgraphService({ goldsky: { projectId: 'PROJECT_ID', subgraphName: 'SUBGRAPH_NAME', version: 'latest' }})
// Direct endpoint configurationconst subgraphService2 = new SubgraphService({ endpoint: 'https://api.goldsky.com/api/public/project_id/subgraph_name'})
// Example: Query for active providers with custom filteringconst activeProviders = await subgraphService.queryProviders({ where: { status: 'Approved' }, orderBy: 'totalDataSets', orderDirection: 'desc', first: 5})
// Example: Find providers for a specific PieceCIDconst providers = await subgraphService.getApprovedProvidersForPieceCID(pieceCid)
Custom Subgraph Service Implementations
Section titled “Custom Subgraph Service Implementations”The SDK supports custom implementations of the SubgraphRetrievalService
interface, allowing you to provide alternative data sources for provider discovery. This is useful for testing, custom integrations, or cases where you need specialized provider selection logic.
// Example: Implementing a custom SubgraphRetrievalServiceclass CustomProviderService implements SubgraphRetrievalService { async getApprovedProvidersForPieceCID(pieceCid) { // Your custom implementation here // Could use a different data source, filtering logic, etc. return [{ owner: '0x123...', pdpUrl: 'https://example.com/pdp', pieceRetrievalUrl: 'https://example.com/retrieval', registeredAt: Date.now(), approvedAt: Date.now() }] }
async getProviderByAddress(address) { // Your custom implementation // ... }}
// Using the custom service with Synapseconst synapse = await Synapse.create({ provider, subgraphService: new CustomProviderService()})
PDP Components
Section titled “PDP Components”The PDP (Proof of Data Possession) system has three main components:
PDP Verifier
Section titled “PDP Verifier”Low-level interface to the PDPVerifier contract for protocol operations.
import { PDPVerifier } from '@filoz/synapse-sdk/pdp'
// Create PDPVerifier instanceconst pdpVerifier = new PDPVerifier(provider, pdpVerifierAddress)
// Check if data set is liveconst isLive = await pdpVerifier.dataSetLive(dataSetId)
// Get data set detailsconst nextPieceId = await pdpVerifier.getNextPieceId(dataSetId)const listener = await pdpVerifier.getDataSetListener(dataSetId)const leafCount = await pdpVerifier.getDataSetLeafCount(dataSetId)
// Extract data set ID from transaction receiptconst dataSetId = await pdpVerifier.extractDataSetIdFromReceipt(receipt)
PDP Server
Section titled “PDP Server”Consolidated interface for all PDP server (Curio) HTTP operations including data sets, uploads, and downloads.
import { PDPServer, PDPAuthHelper } from '@filoz/synapse-sdk/pdp'
// Create server instance with auth helperconst authHelper = new PDPAuthHelper(warmStorageAddress, signer, chainId)const pdpServer = new PDPServer(authHelper, 'https://pdp.provider.com', 'https://pdp.provider.com')
// Create a data setconst { txHash, statusUrl } = await pdpServer.createDataSet( clientDataSetId, // number payee, // string (service provider address) withCDN, // boolean recordKeeper // string (Warm Storage contract address))
// Check creation statusconst status = await pdpServer.getDataSetCreationStatus(txHash)console.log(`Status: ${status.txStatus}, Data Set ID: ${status.dataSetId}`)
// Add pieces to data set (returns transaction tracking info)const addResult = await pdpServer.addPieces( dataSetId, // number (PDPVerifier data set ID) clientDataSetId, // number nextPieceId, // number (must match chain state) pieceDataArray // Array of { cid: string | PieceCID, rawSize: number })// addResult: { message: string, txHash?: string, statusUrl?: string }
// Check piece addition status (for new servers with transaction tracking)if (addResult.txHash) { const status = await pdpServer.getPieceAdditionStatus(dataSetId, addResult.txHash) console.log(`Status: ${status.txStatus}, Piece IDs: ${status.confirmedPieceIds}`)}
// Upload a piececonst { pieceCid, size } = await pdpServer.uploadPiece(data, 'my-file.dat')
// Find existing piececonst piece = await pdpServer.findPiece(pieceCid, size)console.log(`Piece found: ${piece.uuid}`)
// Download a piececonst data = await pdpServer.downloadPiece(pieceCid)
// Get data set detailsconst dataSet = await pdpServer.getDataSet(dataSetId)console.log(`Data set ${dataSet.id} has ${dataSet.pieces.length} pieces`)
PDP Auth Helper
Section titled “PDP Auth Helper”Sign EIP-712 typed data for PDP operations. Compatible with MetaMask and other browser wallets.
import { PDPAuthHelper } from '@filoz/synapse-sdk/pdp'
// Create auth helperconst authHelper = new PDPAuthHelper(warmStorageAddress, signer, chainId)
// Sign operationsconst createDataSetSig = await authHelper.signCreateDataSet( clientDataSetId, // number payeeAddress, // string withCDN // boolean)
const addPiecesSig = await authHelper.signAddPieces( clientDataSetId, // number firstPieceId, // number pieceDataArray // Array of { cid: string | PieceCID, rawSize: number })
// All signatures return { signature, v, r, s, signedData }
PieceCID Utilities
Section titled “PieceCID Utilities”Utilities for calculating PieceCIDs and converting between formats.
import { calculate, asPieceCID, asLegacyPieceCID, createPieceCIDStream } from '@filoz/synapse-sdk/piece'
// Calculate PieceCID from dataconst data = new Uint8Array([1, 2, 3, 4])const pieceCid = calculate(data)console.log(pieceCid.toString()) // bafkzcib...
// Validate and convert PieceCID strings and CIDsconst convertedPieceCid = asPieceCID('bafkzcibcd4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy')if (convertedPieceCid !== null) { console.log('Valid PieceCID:', convertedPieceCid.toString())}
// Stream-based PieceCID calculation; compatible with Web Streams APIconst { stream, getPieceCID } = createPieceCIDStream()// Pipe data through stream, then call getPieceCID() for result
// Convert to LegacyPieceCID for compatibility with external Filecoin servicesconst legacyPieceCid = asLegacyPieceCID(convertedPieceCid)if (legacyPieceCid !== null) { console.log('Valid LegacyPieceCID:', legacyPieceCid.toString()) // Valid LegacyPieceCID: baga6ea4seaqdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy}