From ff5743eacff41b2520421c7f2a342a8e8ee8ce53 Mon Sep 17 00:00:00 2001 From: Aashish Date: Wed, 8 Oct 2025 20:04:59 +0530 Subject: [PATCH 1/6] feat: add ABI fetcher script for direct and proxy contracts via Filfox API --- packages/synapse-sdk/src/script/abiFetcher.ts | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 packages/synapse-sdk/src/script/abiFetcher.ts diff --git a/packages/synapse-sdk/src/script/abiFetcher.ts b/packages/synapse-sdk/src/script/abiFetcher.ts new file mode 100644 index 00000000..3800f74c --- /dev/null +++ b/packages/synapse-sdk/src/script/abiFetcher.ts @@ -0,0 +1,94 @@ +import type { Address } from 'viem'; + +// Define the type for the contract object wagmi uses +export type ContractConfig = { + name: string; + address: Address; + chainId: number; + isProxy?: boolean; +}; + +interface FilfoxProxyResponse { + proxyImpl: string | null; + abi: string | null; +} + +// Unified ABI fetcher: routes to proxy or direct ABI fetch logic based on contract type. +// If the contract is a proxy (isProxy=true), fetches the implementation ABI; otherwise, fetches the contract's own ABI. +export async function fetchContractAbi(contract: ContractConfig): Promise<{ body: string }> { + if (contract.isProxy) { + return fetchProxyAbi(contract); + } else { + return fetchDirectAbi(contract); + } +} + +/** + * Fetches the ABI for contract's implementation from Filfox. + * @param contract The contract configuration from wagmi. + * @returns A promise resolving to the ABI content for wagmi. + */ +async function fetchDirectAbi(contract: ContractConfig): Promise<{ body: string }> { + return fetchAbiFromAddress(contract.address, contract.name, contract.chainId); +} + +/** + * Fetches the ABI for a proxy contract's implementation from Filfox. + * @param contract The contract configuration from wagmi. + * @returns A promise resolving to the ABI content for wagmi. + */ +async function fetchProxyAbi(contract: ContractConfig): Promise<{ body: string }> { + // 1. Fetch the implementation address from the proxy contract. + const proxyUrl = `https://filfox.info/api/v1/address/${contract.address}/contract`; + const proxyResponse = await fetch(proxyUrl, { + headers: { 'Accept': 'application/json' }, + }); + if (!proxyResponse.ok) { + throw new Error( + `Failed to fetch data for proxy contract. Status: ${proxyResponse.status}`, + ); + } + const proxyData = await proxyResponse.json() as FilfoxProxyResponse; + const implementationAddress = proxyData?.proxyImpl; + if (!implementationAddress || implementationAddress === "null") { + throw new Error( + `Could not find implementation address ('proxyImpl') in API response for ${contract.name}.`, + ); + } + + // 2. Fetch the ABI from the implementation contract using the helper + return fetchAbiFromAddress(implementationAddress as Address, contract.name, contract.chainId); +} + +// Internal helper to fetch and parse ABI from Filfox for a given address +async function fetchAbiFromAddress(address: Address, name: string, chainId: number): Promise<{ body: string }> { + try { + const url = `https://filfox.info/api/v1/address/${address}/contract`; + const response = await fetch(url, { + headers: { 'Accept': 'application/json' }, + }); + if (!response.ok) { + throw new Error( + `Failed to fetch data for contract. Status: ${response.status}`, + ); + } + const data = await response.json() as FilfoxProxyResponse; + const abiString = data?.abi; + if (typeof abiString !== 'string' || abiString.length === 0) { + throw new Error( + `Failed to parse ABI. The '.abi' field may be missing, null, or not a valid string.` + ); + } + const abi = JSON.parse(abiString); + console.log(`Successfully fetched ABI for ${name}.`); + return { + body: JSON.stringify(abi, null, 2), + }; + } catch (error) { + console.error( + `Failed to fetch ABI for ${name} on chain ${chainId}:`, + error, + ); + throw error; + } +} \ No newline at end of file From 18c0002c6c3fd78217dfe7dfb26b913a10f26ac8 Mon Sep 17 00:00:00 2001 From: Aashish Date: Wed, 8 Oct 2025 20:20:09 +0530 Subject: [PATCH 2/6] style: fix formatting --- .../synapse-sdk/src/script/abi-fetcher.ts | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 packages/synapse-sdk/src/script/abi-fetcher.ts diff --git a/packages/synapse-sdk/src/script/abi-fetcher.ts b/packages/synapse-sdk/src/script/abi-fetcher.ts new file mode 100644 index 00000000..2370f391 --- /dev/null +++ b/packages/synapse-sdk/src/script/abi-fetcher.ts @@ -0,0 +1,83 @@ +import type { Address } from 'viem' + +// Define the type for the contract object wagmi uses +export type ContractConfig = { + name: string + address: Address + chainId: number + isProxy?: boolean +} + +interface FilfoxProxyResponse { + proxyImpl: string | null + abi: string | null +} + +// Unified ABI fetcher: routes to proxy or direct ABI fetch logic based on contract type. +// If the contract is a proxy (isProxy=true), fetches the implementation ABI; otherwise, fetches the contract's own ABI. +export async function fetchContractAbi(contract: ContractConfig): Promise<{ body: string }> { + if (contract.isProxy) { + return fetchProxyAbi(contract) + } else { + return fetchDirectAbi(contract) + } +} + +/** + * Fetches the ABI for contract's implementation from Filfox. + * @param contract The contract configuration from wagmi. + * @returns A promise resolving to the ABI content for wagmi. + */ +async function fetchDirectAbi(contract: ContractConfig): Promise<{ body: string }> { + return fetchAbiFromAddress(contract.address, contract.name, contract.chainId) +} + +/** + * Fetches the ABI for a proxy contract's implementation from Filfox. + * @param contract The contract configuration from wagmi. + * @returns A promise resolving to the ABI content for wagmi. + */ +async function fetchProxyAbi(contract: ContractConfig): Promise<{ body: string }> { + // 1. Fetch the implementation address from the proxy contract. + const proxyUrl = `https://filfox.info/api/v1/address/${contract.address}/contract` + const proxyResponse = await fetch(proxyUrl, { + headers: { Accept: 'application/json' }, + }) + if (!proxyResponse.ok) { + throw new Error(`Failed to fetch data for proxy contract. Status: ${proxyResponse.status}`) + } + const proxyData = (await proxyResponse.json()) as FilfoxProxyResponse + const implementationAddress = proxyData?.proxyImpl + if (!implementationAddress || implementationAddress === 'null') { + throw new Error(`Could not find implementation address ('proxyImpl') in API response for ${contract.name}.`) + } + + // 2. Fetch the ABI from the implementation contract using the helper + return fetchAbiFromAddress(implementationAddress as Address, contract.name, contract.chainId) +} + +// Internal helper to fetch and parse ABI from Filfox for a given address +async function fetchAbiFromAddress(address: Address, name: string, chainId: number): Promise<{ body: string }> { + try { + const url = `https://filfox.info/api/v1/address/${address}/contract` + const response = await fetch(url, { + headers: { Accept: 'application/json' }, + }) + if (!response.ok) { + throw new Error(`Failed to fetch data for contract. Status: ${response.status}`) + } + const data = (await response.json()) as FilfoxProxyResponse + const abiString = data?.abi + if (typeof abiString !== 'string' || abiString.length === 0) { + throw new Error(`Failed to parse ABI. The '.abi' field may be missing, null, or not a valid string.`) + } + const abi = JSON.parse(abiString) + console.log(`Successfully fetched ABI for ${name}.`) + return { + body: JSON.stringify(abi, null, 2), + } + } catch (error) { + console.error(`Failed to fetch ABI for ${name} on chain ${chainId}:`, error) + throw error + } +} From 9f6c83eb6b5ecd1dbce915ba02cae44d053d9a4e Mon Sep 17 00:00:00 2001 From: Aashish Date: Wed, 8 Oct 2025 20:23:25 +0530 Subject: [PATCH 3/6] fix: removeed abiFetcher.ts --- packages/synapse-sdk/src/script/abiFetcher.ts | 94 ------------------- 1 file changed, 94 deletions(-) delete mode 100644 packages/synapse-sdk/src/script/abiFetcher.ts diff --git a/packages/synapse-sdk/src/script/abiFetcher.ts b/packages/synapse-sdk/src/script/abiFetcher.ts deleted file mode 100644 index 3800f74c..00000000 --- a/packages/synapse-sdk/src/script/abiFetcher.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { Address } from 'viem'; - -// Define the type for the contract object wagmi uses -export type ContractConfig = { - name: string; - address: Address; - chainId: number; - isProxy?: boolean; -}; - -interface FilfoxProxyResponse { - proxyImpl: string | null; - abi: string | null; -} - -// Unified ABI fetcher: routes to proxy or direct ABI fetch logic based on contract type. -// If the contract is a proxy (isProxy=true), fetches the implementation ABI; otherwise, fetches the contract's own ABI. -export async function fetchContractAbi(contract: ContractConfig): Promise<{ body: string }> { - if (contract.isProxy) { - return fetchProxyAbi(contract); - } else { - return fetchDirectAbi(contract); - } -} - -/** - * Fetches the ABI for contract's implementation from Filfox. - * @param contract The contract configuration from wagmi. - * @returns A promise resolving to the ABI content for wagmi. - */ -async function fetchDirectAbi(contract: ContractConfig): Promise<{ body: string }> { - return fetchAbiFromAddress(contract.address, contract.name, contract.chainId); -} - -/** - * Fetches the ABI for a proxy contract's implementation from Filfox. - * @param contract The contract configuration from wagmi. - * @returns A promise resolving to the ABI content for wagmi. - */ -async function fetchProxyAbi(contract: ContractConfig): Promise<{ body: string }> { - // 1. Fetch the implementation address from the proxy contract. - const proxyUrl = `https://filfox.info/api/v1/address/${contract.address}/contract`; - const proxyResponse = await fetch(proxyUrl, { - headers: { 'Accept': 'application/json' }, - }); - if (!proxyResponse.ok) { - throw new Error( - `Failed to fetch data for proxy contract. Status: ${proxyResponse.status}`, - ); - } - const proxyData = await proxyResponse.json() as FilfoxProxyResponse; - const implementationAddress = proxyData?.proxyImpl; - if (!implementationAddress || implementationAddress === "null") { - throw new Error( - `Could not find implementation address ('proxyImpl') in API response for ${contract.name}.`, - ); - } - - // 2. Fetch the ABI from the implementation contract using the helper - return fetchAbiFromAddress(implementationAddress as Address, contract.name, contract.chainId); -} - -// Internal helper to fetch and parse ABI from Filfox for a given address -async function fetchAbiFromAddress(address: Address, name: string, chainId: number): Promise<{ body: string }> { - try { - const url = `https://filfox.info/api/v1/address/${address}/contract`; - const response = await fetch(url, { - headers: { 'Accept': 'application/json' }, - }); - if (!response.ok) { - throw new Error( - `Failed to fetch data for contract. Status: ${response.status}`, - ); - } - const data = await response.json() as FilfoxProxyResponse; - const abiString = data?.abi; - if (typeof abiString !== 'string' || abiString.length === 0) { - throw new Error( - `Failed to parse ABI. The '.abi' field may be missing, null, or not a valid string.` - ); - } - const abi = JSON.parse(abiString); - console.log(`Successfully fetched ABI for ${name}.`); - return { - body: JSON.stringify(abi, null, 2), - }; - } catch (error) { - console.error( - `Failed to fetch ABI for ${name} on chain ${chainId}:`, - error, - ); - throw error; - } -} \ No newline at end of file From d4dab4463b45e60418b29f51e00865ae42a44830 Mon Sep 17 00:00:00 2001 From: Aashish Date: Sun, 12 Oct 2025 01:00:26 +0530 Subject: [PATCH 4/6] feat: add support for calibration Filfox ABI fetching in abi-fetcher --- packages/synapse-sdk/src/script/abi-fetcher.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/synapse-sdk/src/script/abi-fetcher.ts b/packages/synapse-sdk/src/script/abi-fetcher.ts index 2370f391..3f764394 100644 --- a/packages/synapse-sdk/src/script/abi-fetcher.ts +++ b/packages/synapse-sdk/src/script/abi-fetcher.ts @@ -39,7 +39,10 @@ async function fetchDirectAbi(contract: ContractConfig): Promise<{ body: string */ async function fetchProxyAbi(contract: ContractConfig): Promise<{ body: string }> { // 1. Fetch the implementation address from the proxy contract. - const proxyUrl = `https://filfox.info/api/v1/address/${contract.address}/contract` + const proxyUrl = + contract.chainId === 314 + ? `https://filfox.info/api/v1/address/${contract.address}/contract` + : `https://calibration.filfox.info/api/v1/address/${contract.address}/contract` const proxyResponse = await fetch(proxyUrl, { headers: { Accept: 'application/json' }, }) @@ -59,7 +62,10 @@ async function fetchProxyAbi(contract: ContractConfig): Promise<{ body: string } // Internal helper to fetch and parse ABI from Filfox for a given address async function fetchAbiFromAddress(address: Address, name: string, chainId: number): Promise<{ body: string }> { try { - const url = `https://filfox.info/api/v1/address/${address}/contract` + const url = + chainId === 314 + ? `https://filfox.info/api/v1/address/${address}/contract` + : `https://calibration.filfox.info/api/v1/address/${address}/contract` const response = await fetch(url, { headers: { Accept: 'application/json' }, }) From c1378155d8bb4dbed49483274e6c8bb6d08be82b Mon Sep 17 00:00:00 2001 From: Aashish Date: Sun, 12 Oct 2025 01:49:37 +0530 Subject: [PATCH 5/6] refactor: restructure wagmi config for dynamic ABI fetching and contract address selection --- packages/synapse-sdk/wagmi.config.ts | 130 ++++++++++++++++----------- 1 file changed, 77 insertions(+), 53 deletions(-) diff --git a/packages/synapse-sdk/wagmi.config.ts b/packages/synapse-sdk/wagmi.config.ts index a7eed4ce..ced440f0 100644 --- a/packages/synapse-sdk/wagmi.config.ts +++ b/packages/synapse-sdk/wagmi.config.ts @@ -1,72 +1,96 @@ -import { defineConfig } from '@wagmi/cli' -import { fetch } from '@wagmi/cli/plugins' -import type { Address } from 'viem' +import type { Config } from '@wagmi/cli' +import type { Abi, Address } from 'viem' +import { fetchContractAbi } from './src/script/abi-fetcher.ts' -const config = defineConfig(() => { +const network = process.env.NETWORK === 'mainnet' ? 'mainnet' : 'calibration' +const chainId = network === 'mainnet' ? 314 : 314159 + +const createConfig = async (): Promise => { const contracts = [ { name: 'Payments', + isProxy: false, address: { - 314: '0x0000000000000000000000000000000000000000' as Address, - 314159: '0x0000000000000000000000000000000000000000' as Address, - }, - }, - { - name: 'FilecoinWarmStorageService', - address: { - 314: '0x0000000000000000000000000000000000000000' as Address, - 314159: '0x0000000000000000000000000000000000000000' as Address, - }, - }, - { - name: 'FilecoinWarmStorageServiceStateView', - address: { - 314: '0x0000000000000000000000000000000000000000' as Address, - 314159: '0x0000000000000000000000000000000000000000' as Address, - }, - }, - { - name: 'PDPVerifier', - address: { - 314: '0x0000000000000000000000000000000000000000' as Address, - 314159: '0x0000000000000000000000000000000000000000' as Address, - }, - }, - { - name: 'ServiceProviderRegistry', - address: { - 314: '0x0000000000000000000000000000000000000000' as Address, - 314159: '0x0000000000000000000000000000000000000000' as Address, + 314: '0x7DaE6F488651ec5CEE38c9DFbd7d31223eAe1DDE' as Address, + 314159: '0x6dB198201F900c17e86D267d7Df82567FB03df5E' as Address, }, }, + // { + // name: 'FilecoinWarmStorageService', + // address: { + // 314: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x0000000000000000000000000000000000000000' as Address, + // }, + // }, + // { + // name: 'FilecoinWarmStorageServiceStateView', + // address: { + // 314: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x0000000000000000000000000000000000000000' as Address, + // }, + // }, + // { + // name: 'PDPVerifier', + // address: { + // 314: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x0000000000000000000000000000000000000000' as Address, + // }, + // }, + // { + // name: 'ServiceProviderRegistry', + // address: { + // 314: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x0000000000000000000000000000000000000000' as Address, + // }, + // }, + // { + // name: 'SessionKeyRegistry', + // address: { + // 314: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x0000000000000000000000000000000000000000' as Address, + // }, + // }, { - name: 'SessionKeyRegistry', + name: 'Usdfc', + isProxy: true, address: { - 314: '0x0000000000000000000000000000000000000000' as Address, - 314159: '0x0000000000000000000000000000000000000000' as Address, + 314: '0x80B98d3aa09ffff255c3ba4A241111Ff1262F045' as Address, + 314159: '0xb3042734b608a1B16e9e86B374A3f3e389B4cDf0' as Address, }, }, ] + // Filter addresses for the selected network + const filteredContracts = contracts.map((contract) => ({ + ...contract, + address: typeof contract.address === 'object' ? contract.address[chainId] : contract.address, + chainId, + })) + + // Fetch all ABIs upfront + const contractsWithAbis = await Promise.all( + filteredContracts.map(async (contract) => { + const result = await fetchContractAbi({ + name: contract.name, + address: contract.address as Address, + chainId: contract.chainId, + isProxy: contract.isProxy, + }) + return { + name: contract.name, + address: contract.address as Address, + abi: JSON.parse(result.body) as Abi, + } + }) + ) + return [ { out: 'src/abis/gen.ts', - plugins: [ - fetch({ - contracts, - cacheDuration: 100, - request(contract) { - const baseUrl = - 'https://raw.githubusercontent.com/FilOzone/filecoin-services/refs/heads/main/service_contracts/abi' - - return { - url: `${baseUrl}/${contract.name}.abi.json`, - } - }, - }), - ], + contracts: contractsWithAbis, + plugins: [], }, ] -}) +} -export default config +export default createConfig From abc30f027fe7736a828e09540d800f962b7cf975 Mon Sep 17 00:00:00 2001 From: Aashish Date: Wed, 15 Oct 2025 12:11:27 +0530 Subject: [PATCH 6/6] chore: update contract addresses for v0.3.0 M3 Calibration Network deployment in wagmi.config.ts --- packages/synapse-sdk/wagmi.config.ts | 51 +++++++++++++++------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/packages/synapse-sdk/wagmi.config.ts b/packages/synapse-sdk/wagmi.config.ts index ced440f0..b0c95591 100644 --- a/packages/synapse-sdk/wagmi.config.ts +++ b/packages/synapse-sdk/wagmi.config.ts @@ -15,39 +15,44 @@ const createConfig = async (): Promise => { 314159: '0x6dB198201F900c17e86D267d7Df82567FB03df5E' as Address, }, }, - // { - // name: 'FilecoinWarmStorageService', - // address: { - // 314: '0x0000000000000000000000000000000000000000' as Address, - // 314159: '0x0000000000000000000000000000000000000000' as Address, - // }, - // }, - // { - // name: 'FilecoinWarmStorageServiceStateView', - // address: { - // 314: '0x0000000000000000000000000000000000000000' as Address, - // 314159: '0x0000000000000000000000000000000000000000' as Address, - // }, - // }, - // { - // name: 'PDPVerifier', - // address: { - // 314: '0x0000000000000000000000000000000000000000' as Address, - // 314159: '0x0000000000000000000000000000000000000000' as Address, - // }, - // }, + { + name: 'FilecoinWarmStorageService', + isProxy: true, + address: { + 314: '0x0000000000000000000000000000000000000000' as Address, + 314159: '0x468342072e0dc86AFFBe15519bc5B1A1aa86e4dc' as Address, + }, + }, + { + name: 'FilecoinWarmStorageServiceStateView', + isProxy: false, + address: { + 314: '0x0000000000000000000000000000000000000000' as Address, + 314159: '0xE4587AAdB97d7B8197aa08E432bAD0D9Cfe3a17F' as Address, + }, + }, + { + name: 'PDPVerifier', + isProxy: true, + address: { + 314: '0x0000000000000000000000000000000000000000' as Address, + 314159: '0x579dD9E561D4Cd1776CF3e52E598616E77D5FBcb' as Address, + }, + }, // { // name: 'ServiceProviderRegistry', + // isProxy: true, // address: { // 314: '0x0000000000000000000000000000000000000000' as Address, - // 314159: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x1096ba1e7BB912136DA8524A22bF71091dc4FDd9' as Address, // }, // }, // { // name: 'SessionKeyRegistry', + // isProxy: false, // address: { // 314: '0x0000000000000000000000000000000000000000' as Address, - // 314159: '0x0000000000000000000000000000000000000000' as Address, + // 314159: '0x97Dd879F5a97A8c761B94746d7F5cfF50AAd4452' as Address, // }, // }, {