Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
76c7db4
feat: add comprehensive devnet support to Synapse SDK
parthshah1 Nov 5, 2025
c1cc858
multicall3 devnet support
parthshah1 Nov 5, 2025
f2ca682
fixing sentry and viem issues, not needed for devnet antithesis
parthshah1 Nov 5, 2025
ab634aa
fixing sentry and viem issues, not needed for devnet antithesis
parthshah1 Nov 5, 2025
03f9d7a
fixing sentry and viem issues, not needed for devnet antithesis
parthshah1 Nov 5, 2025
d5c134a
fixing imports using relative paths
parthshah1 Nov 5, 2025
b64bd46
fixing devnet issues in util scripts
parthshah1 Nov 5, 2025
2f2e2f8
encodepdp offering fix (try)
parthshah1 Nov 5, 2025
150d824
encodepdp offering fix (try 2)
parthshah1 Nov 5, 2025
0d03ff7
adding devnet address for e2e tests
parthshah1 Nov 5, 2025
ba1a0e2
adding rpc url via env
parthshah1 Nov 5, 2025
7f7d818
debugging timeout
parthshah1 Nov 5, 2025
b5cfe2b
debugging timeout b2
parthshah1 Nov 5, 2025
117b48f
curio detailed logs
parthshah1 Nov 5, 2025
027d3a3
curio detailed logs fix
parthshah1 Nov 5, 2025
544bafa
devnet defaults for synapse instance
parthshah1 Nov 5, 2025
ae299db
private key via env file
parthshah1 Nov 7, 2025
e6fe528
testing debug
parthshah1 Nov 10, 2025
742aa96
Merge branch 'master' of https://github.com/parthshah1/synapse-sdk in…
parthshah1 Nov 10, 2025
1b395bd
e2e test
parthshah1 Nov 10, 2025
f264a8b
e2e test v2
parthshah1 Nov 10, 2025
b7f6d38
recordkeeper contract change
parthshah1 Nov 10, 2025
b2a5557
debug warmstorage recordkeeper
parthshah1 Nov 10, 2025
4ec42f5
debug warmstorage recordkeeper v2
parthshah1 Nov 10, 2025
2ba2edd
debug multicall3 contract
parthshah1 Nov 13, 2025
cf1a02d
changing pdp to warmstorage
parthshah1 Nov 13, 2025
985c6c3
debugging contract addresses
parthshah1 Nov 13, 2025
b72e4b5
more logging for pdp request
parthshah1 Nov 14, 2025
0b545e3
chore: remove debugging code added during devnet development
parthshah1 Nov 20, 2025
dc4a702
Merge branch 'FilOzone:master' into devnet-support-v2
parthshah1 Nov 24, 2025
cac3bb5
chore: remove debugging code from sp.ts
parthshah1 Nov 24, 2025
3c61c50
chore: revert telemetry changes to upstream/master
parthshah1 Nov 24, 2025
419df6b
chore: revert viem.ts changes to upstream/master
parthshah1 Nov 24, 2025
e912ba1
reverting some debuging for PR
parthshah1 Nov 25, 2025
be2a9af
chore: revert non-devnet changes to upstream/master
parthshah1 Nov 26, 2025
2c6b729
Merge branch 'FilOzone:master' into devnet-support-v2
parthshah1 Nov 26, 2025
cd518a7
Merge branch 'devnet-support-v2' of https://github.com/parthshah1/syn…
parthshah1 Nov 26, 2025
4f63f83
synapse-sdk devnet test
parthshah1 Nov 26, 2025
45818d5
adding devnet support to util scripts
parthshah1 Nov 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions packages/synapse-sdk/src/payments/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class PaymentsService {
private readonly _paymentsAddress: string
private readonly _usdfcAddress: string
private readonly _disableNonceManager: boolean
private readonly _multicall3Address: string | null
// Cached contract instances
private _usdfcContract: ethers.Contract | null = null
private _paymentsContract: ethers.Contract | null = null
Expand All @@ -60,13 +61,15 @@ export class PaymentsService {
signer: ethers.Signer,
paymentsAddress: string,
usdfcAddress: string,
disableNonceManager: boolean
disableNonceManager: boolean,
multicall3Address: string | null = null
) {
this._provider = provider
this._signer = signer
this._paymentsAddress = paymentsAddress
this._usdfcAddress = usdfcAddress
this._disableNonceManager = disableNonceManager
this._multicall3Address = multicall3Address
}

/**
Expand Down Expand Up @@ -108,7 +111,15 @@ export class PaymentsService {
const chainId = CHAIN_IDS[networkType]

// Setup Multicall3 for batched RPC calls
const multicall3Address = CONTRACT_ADDRESSES.MULTICALL3[networkType]
const multicall3Address =
this._multicall3Address ?? CONTRACT_ADDRESSES.MULTICALL3[networkType as keyof typeof CONTRACT_ADDRESSES.MULTICALL3]
if (!multicall3Address) {
throw createError(
'PaymentsService',
'_getPermitSignature',
`No Multicall3 address available for network: ${networkType}`
)
}
const multicall = new ethers.Contract(multicall3Address, CONTRACT_ABIS.MULTICALL3, this._provider)

// Create interfaces for encoding/decoding
Expand Down
17 changes: 11 additions & 6 deletions packages/synapse-sdk/src/session/key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,20 @@ export class SessionKey {
private readonly _registry: ethers.Contract
private readonly _signer: ethers.Signer
private readonly _owner: ethers.Signer
private readonly _multicall3Address: string | null

public constructor(
provider: ethers.Provider,
sessionKeyRegistryAddress: string,
signer: ethers.Signer,
owner: ethers.Signer
owner: ethers.Signer,
multicall3Address: string | null = null
) {
this._provider = provider
this._registry = new ethers.Contract(sessionKeyRegistryAddress, CONTRACT_ABIS.SESSION_KEY_REGISTRY, owner)
this._signer = signer
this._owner = owner
this._multicall3Address = multicall3Address
}

getSigner(): ethers.Signer {
Expand All @@ -78,11 +81,13 @@ export class SessionKey {
async fetchExpiries(permissions: string[] = PDP_PERMISSIONS): Promise<Record<string, bigint>> {
const network = await getFilecoinNetworkType(this._provider)

const multicall = new ethers.Contract(
CONTRACT_ADDRESSES.MULTICALL3[network],
CONTRACT_ABIS.MULTICALL3,
this._provider
)
const multicall3Address =
this._multicall3Address ?? CONTRACT_ADDRESSES.MULTICALL3[network as keyof typeof CONTRACT_ADDRESSES.MULTICALL3]
if (!multicall3Address) {
throw new Error(`No Multicall3 address available for network: ${network}`)
}

const multicall = new ethers.Contract(multicall3Address, CONTRACT_ABIS.MULTICALL3, this._provider)
const registryInterface = new ethers.Interface(CONTRACT_ABIS.SESSION_KEY_REGISTRY)

const [ownerAddress, signerAddress, registryAddress] = await Promise.all([
Expand Down
10 changes: 8 additions & 2 deletions packages/synapse-sdk/src/sp-registry/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ import type {
export class SPRegistryService {
private readonly _provider: ethers.Provider
private readonly _registryAddress: string
private readonly _multicall3Address: string | null
private _registryContract: ethers.Contract | null = null

/**
* Constructor for SPRegistryService
*/
constructor(provider: ethers.Provider, registryAddress: string) {
constructor(provider: ethers.Provider, registryAddress: string, multicall3Address: string | null = null) {
this._provider = provider
this._registryAddress = registryAddress
this._multicall3Address = multicall3Address
}

/**
Expand Down Expand Up @@ -453,7 +455,11 @@ export class SPRegistryService {
*/
private async _getProvidersWithMulticall(providerIds: number[]): Promise<ProviderInfo[]> {
const network = await getFilecoinNetworkType(this._provider)
const multicall3Address = CONTRACT_ADDRESSES.MULTICALL3[network]
const multicall3Address =
this._multicall3Address ?? CONTRACT_ADDRESSES.MULTICALL3[network as keyof typeof CONTRACT_ADDRESSES.MULTICALL3]
if (!multicall3Address) {
throw new Error(`No Multicall3 address available for network: ${network}`)
}
const multicall = new ethers.Contract(multicall3Address, CONTRACT_ABIS.MULTICALL3, this._provider)
const iface = new ethers.Interface(CONTRACT_ABIS.SERVICE_PROVIDER_REGISTRY)

Expand Down
140 changes: 121 additions & 19 deletions packages/synapse-sdk/src/synapse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ import type {
SubgraphConfig,
SynapseOptions,
} from './types.ts'
import { CHAIN_IDS, CONTRACT_ADDRESSES, getFilecoinNetworkType } from './utils/index.ts'
import {
CHAIN_IDS,
CONTRACT_ADDRESSES,
GENESIS_TIMESTAMPS,
getFilecoinNetworkType,
queryGenesisTimestamp,
} from './utils/index.ts'
import { WarmStorageService } from './warm-storage/index.ts'

export class Synapse {
Expand All @@ -36,6 +42,8 @@ export class Synapse {
private readonly _pieceRetriever: PieceRetriever
private readonly _storageManager: StorageManager
private _session: SessionKey | null = null
private readonly _genesisTimestamp: number
private readonly _multicall3Address: string

/**
* Create a new Synapse instance with async initialization.
Expand Down Expand Up @@ -118,31 +126,59 @@ export class Synapse {
}

// Final network validation
if (network !== 'mainnet' && network !== 'calibration') {
throw new Error(`Invalid network: ${String(network)}. Only 'mainnet' and 'calibration' are supported.`)
if (network !== 'mainnet' && network !== 'calibration' && network !== 'devnet') {
throw new Error(`Invalid network: ${String(network)}. Only 'mainnet', 'calibration', and 'devnet' are supported.`)
}

const genesisTimestamp =
options.genesisTimestamp ??
(network === 'devnet' ? await queryGenesisTimestamp(provider) : GENESIS_TIMESTAMPS[network])

const resolvedMulticall3Address =
options.multicall3Address ?? CONTRACT_ADDRESSES.MULTICALL3[network as keyof typeof CONTRACT_ADDRESSES.MULTICALL3]
if (!resolvedMulticall3Address) {
throw new Error(
network === 'devnet'
? 'multicall3Address is required when using devnet'
: `No Multicall3 address configured for network: ${network}`
)
}

// Create Warm Storage service with initialized addresses
const warmStorageAddress = options.warmStorageAddress ?? CONTRACT_ADDRESSES.WARM_STORAGE[network]
if (!warmStorageAddress) {
throw new Error(`No Warm Storage address configured for network: ${network}`)
const resolvedWarmStorageAddress =
options.warmStorageAddress ?? CONTRACT_ADDRESSES.WARM_STORAGE[network as keyof typeof CONTRACT_ADDRESSES.WARM_STORAGE]
if (!resolvedWarmStorageAddress) {
throw new Error(
network === 'devnet'
? 'warmStorageAddress is required when using devnet'
: `No Warm Storage address configured for network: ${network}`
)
}
const warmStorageService = await WarmStorageService.create(provider, warmStorageAddress)
const warmStorageService = await WarmStorageService.create(
provider,
resolvedWarmStorageAddress,
resolvedMulticall3Address,
options.warmStorageViewAddress ?? null
)

const withCDNEnabled = network !== 'devnet' && options.withCDN === true
const withIpniEnabled = network === 'devnet' ? false : options.withIpni

// Create payments service with discovered addresses
const paymentsAddress = warmStorageService.getPaymentsAddress()
const usdfcAddress = warmStorageService.getUSDFCTokenAddress()
const usdfcAddress = options.usdfcAddress ?? warmStorageService.getUSDFCTokenAddress()
const payments = new PaymentsService(
provider,
signer,
paymentsAddress,
usdfcAddress,
options.disableNonceManager === true
options.disableNonceManager === true,
resolvedMulticall3Address
)

// Create SPRegistryService for use in retrievers
const registryAddress = warmStorageService.getServiceProviderRegistryAddress()
const spRegistry = new SPRegistryService(provider, registryAddress)
const spRegistry = new SPRegistryService(provider, registryAddress, resolvedMulticall3Address)

// Initialize piece retriever (use provided or create default)
let pieceRetriever: PieceRetriever
Expand All @@ -154,7 +190,7 @@ export class Synapse {

// Check for subgraph option
let baseRetriever: PieceRetriever = chainRetriever
if (options.subgraphConfig != null || options.subgraphService != null) {
if (withIpniEnabled !== false && (options.subgraphConfig != null || options.subgraphService != null)) {
const subgraphService =
options.subgraphService != null
? options.subgraphService
Expand All @@ -175,12 +211,14 @@ export class Synapse {
provider,
network,
payments,
options.withCDN === true,
warmStorageAddress,
withCDNEnabled,
resolvedWarmStorageAddress,
warmStorageService,
pieceRetriever,
options.dev === false,
options.withIpni
withIpniEnabled,
genesisTimestamp,
resolvedMulticall3Address
)
}

Expand All @@ -190,12 +228,13 @@ export class Synapse {
network: FilecoinNetworkType,
payments: PaymentsService,
withCDN: boolean,

warmStorageAddress: string,
warmStorageService: WarmStorageService,
pieceRetriever: PieceRetriever,
dev: boolean,
withIpni?: boolean
withIpni: boolean | undefined,
genesisTimestamp: number,
multicall3Address: string
) {
this._signer = signer
this._provider = provider
Expand All @@ -206,6 +245,8 @@ export class Synapse {
this._pieceRetriever = pieceRetriever
this._warmStorageAddress = warmStorageAddress
this._session = null
this._genesisTimestamp = genesisTimestamp
this._multicall3Address = multicall3Address

// Initialize StorageManager
this._storageManager = new StorageManager(
Expand Down Expand Up @@ -273,7 +314,8 @@ export class Synapse {
this._provider,
this._warmStorageService.getSessionKeyRegistryAddress(),
sessionKeySigner,
this._signer
this._signer,
this._multicall3Address
)
}

Expand Down Expand Up @@ -314,7 +356,27 @@ export class Synapse {
* @returns The numeric chain ID
*/
getChainId(): number {
return this._network === 'mainnet' ? CHAIN_IDS.mainnet : CHAIN_IDS.calibration
return this._network === 'mainnet'
? CHAIN_IDS.mainnet
: this._network === 'calibration'
? CHAIN_IDS.calibration
: CHAIN_IDS.devnet
}

/**
* Gets the genesis timestamp for the current network
* @returns Genesis timestamp in seconds (Unix timestamp)
*/
getGenesisTimestamp(): number {
return this._genesisTimestamp
}

/**
* Gets the Multicall3 contract address in use
* @returns The Multicall3 address as a string
*/
getMulticall3Address(): string {
return this._multicall3Address
}

/**
Expand All @@ -341,6 +403,46 @@ export class Synapse {
return this._warmStorageService.getPDPVerifierAddress()
}

/**
* Gets the USDFC token address for the current network
* @returns The USDFC token address
*/
getUSDFCTokenAddress(): string {
return this._warmStorageService.getUSDFCTokenAddress()
}

/**
* Gets the Service Provider Registry address for the current network
* @returns The Service Provider Registry address
*/
getServiceProviderRegistryAddress(): string {
return this._warmStorageService.getServiceProviderRegistryAddress()
}

/**
* Gets the Session Key Registry address for the current network
* @returns The Session Key Registry address
*/
getSessionKeyRegistryAddress(): string {
return this._warmStorageService.getSessionKeyRegistryAddress()
}

/**
* Gets the Warm Storage View contract address for the current network
* @returns The Warm Storage View contract address
*/
getWarmStorageViewAddress(): string {
return this._warmStorageService.getViewContractAddress()
}

/**
* Gets the FilBeam Beneficiary address for the current network
* @returns The FilBeam Beneficiary address
*/
getFilBeamBeneficiaryAddress(): string {
return this._warmStorageService.getFilBeamBeneficiaryAddress()
}

/**
* Gets the payment service instance
* @returns The payment service
Expand Down Expand Up @@ -436,7 +538,7 @@ export class Synapse {

// Create SPRegistryService
const registryAddress = this._warmStorageService.getServiceProviderRegistryAddress()
const spRegistry = new SPRegistryService(this._provider, registryAddress)
const spRegistry = new SPRegistryService(this._provider, registryAddress, this._multicall3Address)

let providerInfo: ProviderInfo | null
if (typeof providerAddress === 'string') {
Expand Down
5 changes: 4 additions & 1 deletion packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,10 @@ function handler(body: RpcRequest, options: JSONRPCOptions) {
return warmStorageCallHandler(data as Hex, options)
}

if (isAddressEqual(CONTRACT_ADDRESSES.MULTICALL3.calibration, to as Address)) {
if (
isAddressEqual(CONTRACT_ADDRESSES.MULTICALL3.calibration, to as Address) ||
isAddressEqual('0x1000000000000000000000000000000000000001' as Address, to as Address)
) {
return multicall3CallHandler(data as Hex, options)
}

Expand Down
Loading
Loading