Skip to content

Components

All components can be imported and used independently for advanced use cases. The SDK is organized to match the external service structure:

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 contract
const depositTx = await paymentsService.deposit(amount) // amount in base units
console.log(`Deposit transaction: ${depositTx.hash}`)
await depositTx.wait() // Wait for confirmation
// Check account info
const info = await paymentsService.accountInfo() // Uses USDFC by default
console.log('Available funds:', info.availableFunds)
// Approve service as operator
const 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

Query and manage service providers registered in the on-chain registry.

import { SPRegistryService } from '@filoz/synapse-sdk/sp-registry'
// Create service instance
const spRegistry = new SPRegistryService(provider, registryAddress)
// Query providers
const allProviders = await spRegistry.getAllActiveProviders()
const provider = await spRegistry.getProvider(providerId)
const providerByAddr = await spRegistry.getProviderByAddress(address)
// Check registration status
const 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 services
await spRegistry.addPDPProduct(signer, pdpOffering, capabilities)
await spRegistry.updatePDPProduct(signer, pdpOffering, capabilities)
await spRegistry.deactivateProduct(signer, 0) // 0 = ProductType.PDP
// Query PDP service details
const pdpService = await spRegistry.getPDPService(providerId)
console.log('Service URL:', pdpService.offering.serviceURL)
console.log('Storage Price:', pdpService.offering.storagePricePerTibPerMonth)

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 method
const warmStorageService = await WarmStorageService.create(provider, warmStorageAddress)
// Storage cost calculations
const 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 upload
const prep = await warmStorageService.prepareStorageUpload({
dataSize: sizeInBytes,
withCDN: false
}, paymentsService)
// Get client data sets with enhanced details
const 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 instance
const managedSets = await warmStorageService.getManagedDataSets(clientAddress)
// Verify data set creation
const verification = await warmStorageService.verifyDataSetCreation(txHash)
if (verification.dataSetLive) {
console.log(`Data set ${verification.dataSetId} is live!`)
}
// Service provider operations
const isApproved = await warmStorageService.isProviderApproved(providerAddress)
const providers = await warmStorageService.getAllApprovedProviders()

The SubgraphService provides access to Synapse-compatible subgraphs for provider discovery, data set tracking, and more.

// Create subgraph service
const subgraphService = new SubgraphService({
goldsky: {
projectId: 'PROJECT_ID',
subgraphName: 'SUBGRAPH_NAME',
version: 'latest'
}
})
// Direct endpoint configuration
const subgraphService2 = new SubgraphService({
endpoint: 'https://api.goldsky.com/api/public/project_id/subgraph_name'
})
// Example: Query for active providers with custom filtering
const activeProviders = await subgraphService.queryProviders({
where: {
status: 'Approved'
},
orderBy: 'totalDataSets',
orderDirection: 'desc',
first: 5
})
// Example: Find providers for a specific PieceCID
const providers = await subgraphService.getApprovedProvidersForPieceCID(pieceCid)

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 SubgraphRetrievalService
class 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 Synapse
const synapse = await Synapse.create({
provider,
subgraphService: new CustomProviderService()
})

The PDP (Proof of Data Possession) system has three main components:

Low-level interface to the PDPVerifier contract for protocol operations.

import { PDPVerifier } from '@filoz/synapse-sdk/pdp'
// Create PDPVerifier instance
const pdpVerifier = new PDPVerifier(provider, pdpVerifierAddress)
// Check if data set is live
const isLive = await pdpVerifier.dataSetLive(dataSetId)
// Get data set details
const nextPieceId = await pdpVerifier.getNextPieceId(dataSetId)
const listener = await pdpVerifier.getDataSetListener(dataSetId)
const leafCount = await pdpVerifier.getDataSetLeafCount(dataSetId)
// Extract data set ID from transaction receipt
const dataSetId = await pdpVerifier.extractDataSetIdFromReceipt(receipt)

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 helper
const authHelper = new PDPAuthHelper(warmStorageAddress, signer, chainId)
const pdpServer = new PDPServer(authHelper, 'https://pdp.provider.com', 'https://pdp.provider.com')
// Create a data set
const { txHash, statusUrl } = await pdpServer.createDataSet(
clientDataSetId, // number
payee, // string (service provider address)
withCDN, // boolean
recordKeeper // string (Warm Storage contract address)
)
// Check creation status
const 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 piece
const { pieceCid, size } = await pdpServer.uploadPiece(data, 'my-file.dat')
// Find existing piece
const piece = await pdpServer.findPiece(pieceCid, size)
console.log(`Piece found: ${piece.uuid}`)
// Download a piece
const data = await pdpServer.downloadPiece(pieceCid)
// Get data set details
const dataSet = await pdpServer.getDataSet(dataSetId)
console.log(`Data set ${dataSet.id} has ${dataSet.pieces.length} pieces`)

Sign EIP-712 typed data for PDP operations. Compatible with MetaMask and other browser wallets.

import { PDPAuthHelper } from '@filoz/synapse-sdk/pdp'
// Create auth helper
const authHelper = new PDPAuthHelper(warmStorageAddress, signer, chainId)
// Sign operations
const 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 }

Utilities for calculating PieceCIDs and converting between formats.

import { calculate, asPieceCID, asLegacyPieceCID, createPieceCIDStream } from '@filoz/synapse-sdk/piece'
// Calculate PieceCID from data
const data = new Uint8Array([1, 2, 3, 4])
const pieceCid = calculate(data)
console.log(pieceCid.toString()) // bafkzcib...
// Validate and convert PieceCID strings and CIDs
const convertedPieceCid = asPieceCID('bafkzcibcd4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy')
if (convertedPieceCid !== null) {
console.log('Valid PieceCID:', convertedPieceCid.toString())
}
// Stream-based PieceCID calculation; compatible with Web Streams API
const { stream, getPieceCID } = createPieceCIDStream()
// Pipe data through stream, then call getPieceCID() for result
// Convert to LegacyPieceCID for compatibility with external Filecoin services
const legacyPieceCid = asLegacyPieceCID(convertedPieceCid)
if (legacyPieceCid !== null) {
console.log('Valid LegacyPieceCID:', legacyPieceCid.toString())
// Valid LegacyPieceCID: baga6ea4seaqdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy
}