diff --git a/packages/synapse-core/src/abis/generated.ts b/packages/synapse-core/src/abis/generated.ts index 9750c6e9..dbedf5b4 100644 --- a/packages/synapse-core/src/abis/generated.ts +++ b/packages/synapse-core/src/abis/generated.ts @@ -3239,6 +3239,19 @@ export const filecoinWarmStorageServiceStateViewAbi = [ ], stateMutability: 'nonpayable', }, + { + type: 'function', + inputs: [ + { name: 'payer', internalType: 'address', type: 'address' }, + { name: 'offset', internalType: 'uint256', type: 'uint256' }, + { name: 'limit', internalType: 'uint256', type: 'uint256' }, + ], + name: 'clientDataSets', + outputs: [ + { name: 'dataSetIds', internalType: 'uint256[]', type: 'uint256[]' }, + ], + stateMutability: 'view', + }, { type: 'function', inputs: [{ name: 'payer', internalType: 'address', type: 'address' }], @@ -3307,6 +3320,36 @@ export const filecoinWarmStorageServiceStateViewAbi = [ outputs: [{ name: 'count', internalType: 'uint256', type: 'uint256' }], stateMutability: 'view', }, + { + type: 'function', + inputs: [ + { name: 'client', internalType: 'address', type: 'address' }, + { name: 'offset', internalType: 'uint256', type: 'uint256' }, + { name: 'limit', internalType: 'uint256', type: 'uint256' }, + ], + name: 'getClientDataSets', + outputs: [ + { + name: 'infos', + internalType: 'struct FilecoinWarmStorageService.DataSetInfoView[]', + type: 'tuple[]', + components: [ + { name: 'pdpRailId', internalType: 'uint256', type: 'uint256' }, + { name: 'cacheMissRailId', internalType: 'uint256', type: 'uint256' }, + { name: 'cdnRailId', internalType: 'uint256', type: 'uint256' }, + { name: 'payer', internalType: 'address', type: 'address' }, + { name: 'payee', internalType: 'address', type: 'address' }, + { name: 'serviceProvider', internalType: 'address', type: 'address' }, + { name: 'commissionBps', internalType: 'uint256', type: 'uint256' }, + { name: 'clientDataSetId', internalType: 'uint256', type: 'uint256' }, + { name: 'pdpEndEpoch', internalType: 'uint256', type: 'uint256' }, + { name: 'providerId', internalType: 'uint256', type: 'uint256' }, + { name: 'dataSetId', internalType: 'uint256', type: 'uint256' }, + ], + }, + ], + stateMutability: 'view', + }, { type: 'function', inputs: [{ name: 'client', internalType: 'address', type: 'address' }], @@ -3333,6 +3376,13 @@ export const filecoinWarmStorageServiceStateViewAbi = [ ], stateMutability: 'view', }, + { + type: 'function', + inputs: [{ name: 'payer', internalType: 'address', type: 'address' }], + name: 'getClientDataSetsLength', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, { type: 'function', inputs: [], @@ -3562,6 +3612,13 @@ export const pdpVerifierAbi = [ ], stateMutability: 'nonpayable', }, + { + type: 'function', + inputs: [], + name: 'FIL_SYBIL_FEE', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'pure', + }, { type: 'function', inputs: [], @@ -3748,6 +3805,25 @@ export const pdpVerifierAbi = [ ], stateMutability: 'view', }, + { + type: 'function', + inputs: [ + { name: 'setId', internalType: 'uint256', type: 'uint256' }, + { + name: 'pieceCid', + internalType: 'struct Cids.Cid', + type: 'tuple', + components: [{ name: 'data', internalType: 'bytes', type: 'bytes' }], + }, + { name: 'startPieceId', internalType: 'uint256', type: 'uint256' }, + { name: 'limit', internalType: 'uint256', type: 'uint256' }, + ], + name: 'findPieceIdsByCid', + outputs: [ + { name: 'pieceIds', internalType: 'uint256[]', type: 'uint256[]' }, + ], + stateMutability: 'view', + }, { type: 'function', inputs: [{ name: 'setId', internalType: 'uint256', type: 'uint256' }], diff --git a/packages/synapse-core/src/mocks/jsonrpc/index.ts b/packages/synapse-core/src/mocks/jsonrpc/index.ts index ff223f2b..6923eeb9 100644 --- a/packages/synapse-core/src/mocks/jsonrpc/index.ts +++ b/packages/synapse-core/src/mocks/jsonrpc/index.ts @@ -505,6 +505,9 @@ export const presets = { getPDPConfig: () => { return [BigInt(2880), BigInt(60), BigInt(1), BigInt(0)] }, + getClientDataSetsLength: () => { + return [1n] + }, }, pdpVerifier: { dataSetLive: () => [true], diff --git a/packages/synapse-core/src/mocks/jsonrpc/warm-storage.ts b/packages/synapse-core/src/mocks/jsonrpc/warm-storage.ts index f7567e34..39a58fca 100644 --- a/packages/synapse-core/src/mocks/jsonrpc/warm-storage.ts +++ b/packages/synapse-core/src/mocks/jsonrpc/warm-storage.ts @@ -20,6 +20,7 @@ export type getAllPieceMetadata = ExtractAbiFunction export type clientNonces = ExtractAbiFunction export type getPDPConfig = ExtractAbiFunction +export type getClientDataSetsLength = ExtractAbiFunction export interface WarmStorageViewOptions { isProviderApproved?: (args: AbiToType) => AbiToType @@ -36,6 +37,9 @@ export interface WarmStorageViewOptions { getPieceMetadata?: (args: AbiToType) => AbiToType clientNonces?: (args: AbiToType) => AbiToType getPDPConfig?: (args: AbiToType) => AbiToType + getClientDataSetsLength?: ( + args: AbiToType + ) => AbiToType } /** @@ -346,6 +350,15 @@ export function warmStorageViewCallHandler(data: Hex, options: JSONRPCOptions): options.warmStorageView.getPDPConfig(args) ) } + case 'getClientDataSetsLength': { + if (!options.warmStorageView?.getClientDataSetsLength) { + throw new Error('Warm Storage View: getClientDataSetsLength is not defined') + } + return encodeAbiParameters( + Abis.fwssView.find((abi) => abi.type === 'function' && abi.name === 'getClientDataSetsLength')!.outputs, + options.warmStorageView.getClientDataSetsLength(args) + ) + } default: { throw new Error(`Warm Storage View: unknown function: ${functionName} with args: ${args}`) diff --git a/packages/synapse-core/src/warm-storage/get-client-data-set-ids.ts b/packages/synapse-core/src/warm-storage/get-client-data-set-ids.ts new file mode 100644 index 00000000..49e23e40 --- /dev/null +++ b/packages/synapse-core/src/warm-storage/get-client-data-set-ids.ts @@ -0,0 +1,139 @@ +import type { Simplify } from 'type-fest' +import type { + Address, + Chain, + Client, + ContractFunctionParameters, + ContractFunctionReturnType, + ReadContractErrorType, + Transport, +} from 'viem' +import { readContract } from 'viem/actions' +import type { fwssView as storageViewAbi } from '../abis/index.ts' +import { asChain } from '../chains.ts' +import type { ActionCallChain } from '../types.ts' + +export namespace getClientDataSetIds { + export type OptionsType = { + /** Client address to fetch data set IDs for. */ + address: Address + /** Starting index (0-based). Use 0 to start from beginning. Defaults to 0. */ + offset?: bigint + /** Maximum number of dataset IDs to return. Use 0 to get all remaining IDs. Defaults to 0. */ + limit?: bigint + /** Warm storage contract address. If not provided, the default is the storage view contract address for the chain. */ + contractAddress?: Address + } + + export type ContractOutputType = ContractFunctionReturnType< + typeof storageViewAbi, + 'pure' | 'view', + 'clientDataSets', + [Address, bigint, bigint] + > + + /** Array of client data set IDs */ + export type OutputType = bigint[] + + export type ErrorType = asChain.ErrorType | ReadContractErrorType +} + +/** + * Get client data set IDs with optional pagination + * + * For large lists, use pagination to avoid gas limit issues. If limit=0, + * returns all remaining IDs starting from offset. + * + * @param client - The client to use to get data set IDs. + * @param options - {@link getClientDataSetIds.OptionsType} + * @returns Array of data set IDs {@link getClientDataSetIds.OutputType} + * @throws Errors {@link getClientDataSetIds.ErrorType} + * + * @example + * ```ts + * import { getClientDataSetIds } from '@filoz/synapse-core/warm-storage' + * import { createPublicClient, http } from 'viem' + * import { calibration } from '@filoz/synapse-core/chains' + * + * const client = createPublicClient({ + * chain: calibration, + * transport: http(), + * }) + * + * // Get first 100 dataset IDs + * const ids = await getClientDataSetIds(client, { + * address: '0x0000000000000000000000000000000000000000', + * offset: 0n, + * limit: 100n, + * }) + * + * console.log(ids) + * ``` + */ +export async function getClientDataSetIds( + client: Client, + options: getClientDataSetIds.OptionsType +): Promise { + const data = await readContract( + client, + getClientDataSetIdsCall({ + chain: client.chain, + address: options.address, + offset: options.offset, + limit: options.limit, + contractAddress: options.contractAddress, + }) + ) + return data as getClientDataSetIds.OutputType +} + +export namespace getClientDataSetIdsCall { + export type OptionsType = Simplify + export type ErrorType = asChain.ErrorType + export type OutputType = ContractFunctionParameters< + typeof storageViewAbi, + 'pure' | 'view', + 'clientDataSets', + [Address, bigint, bigint] + > +} + +/** + * Create a call to the {@link getClientDataSetIds} function for use with the Viem multicall, readContract, or simulateContract functions. + * + * @param options - {@link getClientDataSetIdsCall.OptionsType} + * @returns The call to the clientDataSets function {@link getClientDataSetIdsCall.OutputType} + * @throws Errors {@link getClientDataSetIdsCall.ErrorType} + * + * @example + * ```ts + * import { getClientDataSetIdsCall } from '@filoz/synapse-core/warm-storage' + * import { createPublicClient, http } from 'viem' + * import { multicall } from 'viem/actions' + * import { calibration } from '@filoz/synapse-core/chains' + * + * const client = createPublicClient({ + * chain: calibration, + * transport: http(), + * }) + * + * // Paginate through IDs in batches of 50 + * const results = await multicall(client, { + * contracts: [ + * getClientDataSetIdsCall({ chain: calibration, address: '0x...', offset: 0n, limit: 50n }), + * getClientDataSetIdsCall({ chain: calibration, address: '0x...', offset: 50n, limit: 50n }), + * ], + * }) + * + * console.log(results) + * ``` + */ +export function getClientDataSetIdsCall(options: getClientDataSetIdsCall.OptionsType) { + const chain = asChain(options.chain) + return { + abi: chain.contracts.fwssView.abi, + address: options.contractAddress ?? chain.contracts.fwssView.address, + functionName: 'clientDataSets', + args: [options.address, options.offset ?? 0n, options.limit ?? 0n], + } satisfies getClientDataSetIdsCall.OutputType +} diff --git a/packages/synapse-core/src/warm-storage/get-client-data-sets-length.ts b/packages/synapse-core/src/warm-storage/get-client-data-sets-length.ts new file mode 100644 index 00000000..24e832d1 --- /dev/null +++ b/packages/synapse-core/src/warm-storage/get-client-data-sets-length.ts @@ -0,0 +1,122 @@ +import type { Simplify } from 'type-fest' +import type { + Address, + Chain, + Client, + ContractFunctionParameters, + ContractFunctionReturnType, + ReadContractErrorType, + Transport, +} from 'viem' +import { readContract } from 'viem/actions' +import type { fwssView as storageViewAbi } from '../abis/index.ts' +import { asChain } from '../chains.ts' +import type { ActionCallChain } from '../types.ts' + +export namespace getClientDataSetsLength { + export type OptionsType = { + /** Client address to count data sets for. */ + address: Address + /** Warm storage contract address. If not provided, the default is the storage view contract address for the chain. */ + contractAddress?: Address + } + + export type ContractOutputType = ContractFunctionReturnType< + typeof storageViewAbi, + 'pure' | 'view', + 'getClientDataSetsLength' + > + + /** Total count of data sets for the client */ + export type OutputType = bigint + + export type ErrorType = asChain.ErrorType | ReadContractErrorType +} + +/** + * Get total count of client data sets + * + * @param client - The client to use to get the data set count. + * @param options - {@link getClientDataSetsLength.OptionsType} + * @returns Total count of data sets {@link getClientDataSetsLength.OutputType} + * @throws Errors {@link getClientDataSetsLength.ErrorType} + * + * @example + * ```ts + * import { getClientDataSetsLength } from '@filoz/synapse-core/warm-storage' + * import { createPublicClient, http } from 'viem' + * import { calibration } from '@filoz/synapse-core/chains' + * + * const client = createPublicClient({ + * chain: calibration, + * transport: http(), + * }) + * + * const count = await getClientDataSetsLength(client, { + * address: '0x0000000000000000000000000000000000000000', + * }) + * + * console.log(count) + * ``` + */ +export async function getClientDataSetsLength( + client: Client, + options: getClientDataSetsLength.OptionsType +): Promise { + const data = await readContract( + client, + getClientDataSetsLengthCall({ + chain: client.chain, + address: options.address, + contractAddress: options.contractAddress, + }) + ) + return data as getClientDataSetsLength.OutputType +} + +export namespace getClientDataSetsLengthCall { + export type OptionsType = Simplify + export type ErrorType = asChain.ErrorType + export type OutputType = ContractFunctionParameters +} + +/** + * Create a call to the {@link getClientDataSetsLength} function for use with the Viem multicall, readContract, or simulateContract functions. + * + * @param options - {@link getClientDataSetsLengthCall.OptionsType} + * @returns The call to the getClientDataSetsLength function {@link getClientDataSetsLengthCall.OutputType} + * @throws Errors {@link getClientDataSetsLengthCall.ErrorType} + * + * @example + * ```ts + * import { getClientDataSetsLengthCall } from '@filoz/synapse-core/warm-storage' + * import { createPublicClient, http } from 'viem' + * import { multicall } from 'viem/actions' + * import { calibration } from '@filoz/synapse-core/chains' + * + * const client = createPublicClient({ + * chain: calibration, + * transport: http(), + * }) + * + * const results = await multicall(client, { + * contracts: [ + * getClientDataSetsLengthCall({ + * chain: calibration, + * address: '0x0000000000000000000000000000000000000000', + * }), + * ], + * }) + * + * console.log(results[0]) + * ``` + */ +export function getClientDataSetsLengthCall(options: getClientDataSetsLengthCall.OptionsType) { + const chain = asChain(options.chain) + return { + abi: chain.contracts.fwssView.abi, + address: options.contractAddress ?? chain.contracts.fwssView.address, + functionName: 'getClientDataSetsLength', + args: [options.address], + } satisfies getClientDataSetsLengthCall.OutputType +} diff --git a/packages/synapse-core/src/warm-storage/get-client-data-sets.ts b/packages/synapse-core/src/warm-storage/get-client-data-sets.ts index 3e2b1774..7a803b1a 100644 --- a/packages/synapse-core/src/warm-storage/get-client-data-sets.ts +++ b/packages/synapse-core/src/warm-storage/get-client-data-sets.ts @@ -19,6 +19,10 @@ export namespace getClientDataSets { export type OptionsType = { /** Client address to fetch data sets for. */ address: Address + /** Starting index (0-based). Use `0` to start from the beginning. Defaults to `0n`. */ + offset?: bigint + /** Maximum number of data sets to return. Use `0` to get all remaining. Defaults to `0n` (all). */ + limit?: bigint /** Warm storage contract address. If not provided, the default is the storage view contract address for the chain. */ contractAddress?: Address } @@ -57,7 +61,7 @@ export namespace getClientDataSets { * }) * * const dataSets = await getClientDataSets(client, { - * client: '0x0000000000000000000000000000000000000000', + * address: '0x0000000000000000000000000000000000000000', * }) * * console.log(dataSets[0]?.dataSetId) @@ -72,6 +76,8 @@ export async function getClientDataSets( getClientDataSetsCall({ chain: client.chain, address: options.address, + offset: options.offset, + limit: options.limit, contractAddress: options.contractAddress, }) ) @@ -81,7 +87,12 @@ export async function getClientDataSets( export namespace getClientDataSetsCall { export type OptionsType = Simplify export type ErrorType = asChain.ErrorType - export type OutputType = ContractFunctionParameters + export type OutputType = ContractFunctionParameters< + typeof storageViewAbi, + 'pure' | 'view', + 'getClientDataSets', + [Address, bigint, bigint] + > } /** @@ -107,7 +118,7 @@ export namespace getClientDataSetsCall { * contracts: [ * getClientDataSetsCall({ * chain: calibration, - * client: '0x0000000000000000000000000000000000000000', + * address: '0x0000000000000000000000000000000000000000', * }), * ], * }) @@ -121,6 +132,6 @@ export function getClientDataSetsCall(options: getClientDataSetsCall.OptionsType abi: chain.contracts.fwssView.abi, address: options.contractAddress ?? chain.contracts.fwssView.address, functionName: 'getClientDataSets', - args: [options.address], + args: [options.address, options.offset ?? 0n, options.limit ?? 0n], } satisfies getClientDataSetsCall.OutputType } diff --git a/packages/synapse-core/src/warm-storage/index.ts b/packages/synapse-core/src/warm-storage/index.ts index c6b0b2c1..763f0b41 100644 --- a/packages/synapse-core/src/warm-storage/index.ts +++ b/packages/synapse-core/src/warm-storage/index.ts @@ -19,7 +19,9 @@ export * from './get-account-total-storage-size.ts' export * from './get-all-data-set-metadata.ts' export * from './get-all-piece-metadata.ts' export * from './get-approved-providers.ts' +export * from './get-client-data-set-ids.ts' export * from './get-client-data-sets.ts' +export * from './get-client-data-sets-length.ts' export * from './get-data-set.ts' export * from './get-pdp-data-set.ts' export * from './get-pdp-data-sets.ts' diff --git a/packages/synapse-core/test/get-client-data-set-ids.test.ts b/packages/synapse-core/test/get-client-data-set-ids.test.ts new file mode 100644 index 00000000..fef5a2bd --- /dev/null +++ b/packages/synapse-core/test/get-client-data-set-ids.test.ts @@ -0,0 +1,100 @@ +import assert from 'assert' +import { setup } from 'iso-web/msw' +import { createPublicClient, http } from 'viem' +import { calibration, mainnet } from '../src/chains.ts' +import { ADDRESSES, JSONRPC, presets } from '../src/mocks/jsonrpc/index.ts' +import { getClientDataSetIds, getClientDataSetIdsCall } from '../src/warm-storage/get-client-data-set-ids.ts' + +describe('getClientDataSetIds', () => { + const server = setup() + + before(async () => { + await server.start() + }) + + after(() => { + server.stop() + }) + + beforeEach(() => { + server.resetHandlers() + }) + + describe('getClientDataSetIdsCall', () => { + it('should create call with calibration chain defaults and default offset/limit', () => { + const call = getClientDataSetIdsCall({ + chain: calibration, + address: ADDRESSES.client1, + }) + + assert.equal(call.functionName, 'clientDataSets') + assert.deepEqual(call.args, [ADDRESSES.client1, 0n, 0n]) + assert.equal(call.address, calibration.contracts.fwssView.address) + assert.equal(call.abi, calibration.contracts.fwssView.abi) + }) + + it('should create call with mainnet chain defaults', () => { + const call = getClientDataSetIdsCall({ + chain: mainnet, + address: ADDRESSES.client1, + }) + + assert.equal(call.functionName, 'clientDataSets') + assert.deepEqual(call.args, [ADDRESSES.client1, 0n, 0n]) + assert.equal(call.address, mainnet.contracts.fwssView.address) + assert.equal(call.abi, mainnet.contracts.fwssView.abi) + }) + + it('should use explicit offset and limit', () => { + const call = getClientDataSetIdsCall({ + chain: calibration, + address: ADDRESSES.client1, + offset: 10n, + limit: 50n, + }) + + assert.equal(call.functionName, 'clientDataSets') + assert.deepEqual(call.args, [ADDRESSES.client1, 10n, 50n]) + }) + + it('should use custom contract address when provided', () => { + const customAddress = '0x1234567890123456789012345678901234567890' + const call = getClientDataSetIdsCall({ + chain: calibration, + address: ADDRESSES.client1, + contractAddress: customAddress, + }) + + assert.equal(call.address, customAddress) + }) + + it('should default offset to 0n when only limit is provided', () => { + const call = getClientDataSetIdsCall({ + chain: calibration, + address: ADDRESSES.client1, + limit: 100n, + }) + + assert.deepEqual(call.args, [ADDRESSES.client1, 0n, 100n]) + }) + }) + + describe('getClientDataSetIds (with mocked RPC)', () => { + it('should fetch client data set IDs', async () => { + server.use(JSONRPC(presets.basic)) + + const client = createPublicClient({ + chain: calibration, + transport: http(), + }) + + const ids = await getClientDataSetIds(client, { + address: ADDRESSES.client1, + }) + + assert.ok(Array.isArray(ids)) + assert.ok(ids.length > 0) + assert.equal(typeof ids[0], 'bigint') + }) + }) +}) diff --git a/packages/synapse-core/test/get-client-data-sets-length.test.ts b/packages/synapse-core/test/get-client-data-sets-length.test.ts new file mode 100644 index 00000000..ab36af08 --- /dev/null +++ b/packages/synapse-core/test/get-client-data-sets-length.test.ts @@ -0,0 +1,80 @@ +import assert from 'assert' +import { setup } from 'iso-web/msw' +import { createPublicClient, http } from 'viem' +import { calibration, mainnet } from '../src/chains.ts' +import { ADDRESSES, JSONRPC, presets } from '../src/mocks/jsonrpc/index.ts' +import { + getClientDataSetsLength, + getClientDataSetsLengthCall, +} from '../src/warm-storage/get-client-data-sets-length.ts' + +describe('getClientDataSetsLength', () => { + const server = setup() + + before(async () => { + await server.start() + }) + + after(() => { + server.stop() + }) + + beforeEach(() => { + server.resetHandlers() + }) + + describe('getClientDataSetsLengthCall', () => { + it('should create call with calibration chain defaults', () => { + const call = getClientDataSetsLengthCall({ + chain: calibration, + address: ADDRESSES.client1, + }) + + assert.equal(call.functionName, 'getClientDataSetsLength') + assert.deepEqual(call.args, [ADDRESSES.client1]) + assert.equal(call.address, calibration.contracts.fwssView.address) + assert.equal(call.abi, calibration.contracts.fwssView.abi) + }) + + it('should create call with mainnet chain defaults', () => { + const call = getClientDataSetsLengthCall({ + chain: mainnet, + address: ADDRESSES.client1, + }) + + assert.equal(call.functionName, 'getClientDataSetsLength') + assert.deepEqual(call.args, [ADDRESSES.client1]) + assert.equal(call.address, mainnet.contracts.fwssView.address) + assert.equal(call.abi, mainnet.contracts.fwssView.abi) + }) + + it('should use custom address when provided', () => { + const customAddress = '0x1234567890123456789012345678901234567890' + const call = getClientDataSetsLengthCall({ + chain: calibration, + address: ADDRESSES.client1, + contractAddress: customAddress, + }) + + assert.equal(call.address, customAddress) + }) + }) + + describe('getClientDataSetsLength (with mocked RPC)', () => { + it('should fetch client data sets length', async () => { + server.use(JSONRPC(presets.basic)) + + const client = createPublicClient({ + chain: calibration, + transport: http(), + }) + + const count = await getClientDataSetsLength(client, { + address: ADDRESSES.client1, + }) + + assert.equal(typeof count, 'bigint') + assert.equal(count, 1n) + }) + }) +}) diff --git a/packages/synapse-core/test/get-client-data-sets.test.ts b/packages/synapse-core/test/get-client-data-sets.test.ts index c7e6e2e5..688e717e 100644 --- a/packages/synapse-core/test/get-client-data-sets.test.ts +++ b/packages/synapse-core/test/get-client-data-sets.test.ts @@ -28,7 +28,7 @@ describe('getClientDataSets', () => { }) assert.equal(call.functionName, 'getClientDataSets') - assert.deepEqual(call.args, [ADDRESSES.client1]) + assert.deepEqual(call.args, [ADDRESSES.client1, 0n, 0n]) assert.equal(call.address, calibration.contracts.fwssView.address) assert.equal(call.abi, calibration.contracts.fwssView.abi) }) @@ -40,7 +40,7 @@ describe('getClientDataSets', () => { }) assert.equal(call.functionName, 'getClientDataSets') - assert.deepEqual(call.args, [ADDRESSES.client1]) + assert.deepEqual(call.args, [ADDRESSES.client1, 0n, 0n]) assert.equal(call.address, mainnet.contracts.fwssView.address) assert.equal(call.abi, mainnet.contracts.fwssView.abi) }) @@ -55,6 +55,28 @@ describe('getClientDataSets', () => { assert.equal(call.address, customAddress) }) + + it('should use paginated args when offset is provided', () => { + const call = getClientDataSetsCall({ + chain: calibration, + address: ADDRESSES.client1, + offset: 10n, + limit: 50n, + }) + + assert.equal(call.functionName, 'getClientDataSets') + assert.deepEqual(call.args, [ADDRESSES.client1, 10n, 50n]) + }) + + it('should default offset/limit to 0n when not provided', () => { + const call = getClientDataSetsCall({ + chain: calibration, + address: ADDRESSES.client1, + }) + + assert.equal(call.functionName, 'getClientDataSets') + assert.deepEqual(call.args, [ADDRESSES.client1, 0n, 0n]) + }) }) describe('getClientDataSets (with mocked RPC)', () => { @@ -87,5 +109,30 @@ describe('getClientDataSets', () => { assert.equal(typeof first.providerId, 'bigint') assert.equal(typeof first.dataSetId, 'bigint') }) + + it('should fetch client data sets with pagination', async () => { + server.use(JSONRPC(presets.basic)) + + const client = createPublicClient({ + chain: calibration, + transport: http(), + }) + + const dataSets = await getClientDataSets(client, { + address: ADDRESSES.client1, + offset: 0n, + limit: 10n, + }) + + assert.ok(dataSets.length > 0) + const [first] = dataSets + assert.ok(first) + if (!first) return + + assert.equal(typeof first.pdpRailId, 'bigint') + assert.equal(typeof first.dataSetId, 'bigint') + assert.equal(typeof first.payer, 'string') + assert.equal(typeof first.payee, 'string') + }) }) }) diff --git a/packages/synapse-core/wagmi.config.ts b/packages/synapse-core/wagmi.config.ts index e0cdddce..40bfcdd9 100644 --- a/packages/synapse-core/wagmi.config.ts +++ b/packages/synapse-core/wagmi.config.ts @@ -5,7 +5,7 @@ import { multicall } from 'viem/actions' import { calibration, mainnet } from './src/chains.ts' // GIT_REF can be one of: '', '' or 'tags/' -const GIT_REF = '44ef7165f7db93e5491a27ce14460143ff9a7d13' +const GIT_REF = 'ed85348ebad54196b5bfefc5cb0dbe7e8bfd6f7c' // v1.2.0 const BASE_URL = `https://raw.githubusercontent.com/FilOzone/filecoin-services/${GIT_REF.replace(/^(?![a-f0-9]{40}$)/, 'refs/')}/service_contracts/abi` const FWSS_ADDRESS_CALIBRATION = '0x02925630df557F957f70E112bA06e50965417CA0' as Address const FWSS_ADDRESS_MAINNET = '0x8408502033C418E1bbC97cE9ac48E5528F371A9f' as Address