): Promise): Promise, options:
const addPieces = await PDP.addPieces({
dataSetId: options.dataSetId,
- clientDataSetId: dataSet.clientDataSetId,
nextPieceId: nextPieceId,
pieces: uploadResponses.map((response) => response.pieceCid),
endpoint: provider[0].serviceURL,
diff --git a/packages/synapse-core/wagmi.config.ts b/packages/synapse-core/wagmi.config.ts
index 30bd1097..886c9f8b 100644
--- a/packages/synapse-core/wagmi.config.ts
+++ b/packages/synapse-core/wagmi.config.ts
@@ -2,41 +2,53 @@ import { defineConfig } from '@wagmi/cli'
import { fetch } from '@wagmi/cli/plugins'
import type { Address } from 'viem'
+// const REF = 'refs/tags/v0.3.0'
+// const REF = '15eeb6dc87db236507add5553a0c76c009705525'
+const REF = 'refs/heads/kubuxu/devnode-contracts'
+const URL = `https://raw.githubusercontent.com/FilOzone/filecoin-services/${REF}/service_contracts/abi`
+
const config: ReturnType = defineConfig(() => {
const contracts = [
{
- name: 'Payments',
+ name: 'FilecoinPayV1',
address: {
314: '0x0000000000000000000000000000000000000000' as Address,
- 314159: '0x1096025c9D6B29E12E2f04965F6E64d564Ce0750' as Address,
+ 314159: '0x09a0fDc2723fAd1A7b8e3e00eE5DF73841df55a0' as Address,
},
},
{
name: 'FilecoinWarmStorageService',
address: {
314: '0x0000000000000000000000000000000000000000' as Address,
- 314159: '0x80617b65FD2EEa1D7fDe2B4F85977670690ed348' as Address,
+ 314159: '0xD3De778C05f89e1240ef70100Fb0d9e5b2eFD258' as Address,
+ },
+ },
+ {
+ name: 'Errors',
+ address: {
+ 314: '0x0000000000000000000000000000000000000000' as Address,
+ 314159: '0x0000000000000000000000000000000000000000' as Address,
},
},
{
name: 'FilecoinWarmStorageServiceStateView',
address: {
314: '0x0000000000000000000000000000000000000000' as Address,
- 314159: '0x87EDE87cEF4BfeFE0374c3470cB3F5be18b739d5' as Address,
+ 314159: '0x0295Ac959317391656fB7fFaA046046eF9C7E18F' as Address,
},
},
{
name: 'PDPVerifier',
address: {
314: '0x0000000000000000000000000000000000000000' as Address,
- 314159: '0x445238Eca6c6aB8Dff1Aa6087d9c05734D22f137' as Address,
+ 314159: '0x06279D540BDCd6CA33B073cEAeA1425B6C68c93d' as Address,
},
},
{
name: 'ServiceProviderRegistry',
address: {
314: '0x0000000000000000000000000000000000000000' as Address,
- 314159: '0xA8a7e2130C27e4f39D1aEBb3D538D5937bCf8ddb' as Address,
+ 314159: '0xc758dB755f59189d8FB3C166Ee372b77d7CFA9D3' as Address,
},
},
{
@@ -54,13 +66,11 @@ const config: ReturnType = defineConfig(() => {
plugins: [
fetch({
contracts,
+
cacheDuration: 100,
request(contract) {
- const baseUrl =
- 'https://raw.githubusercontent.com/FilOzone/filecoin-services/refs/tags/alpha/calibnet/0x80617b65FD2EEa1D7fDe2B4F85977670690ed348-v2/service_contracts/abi'
-
return {
- url: `${baseUrl}/${contract.name}.abi.json`,
+ url: `${URL}/${contract.name}.abi.json`,
}
},
}),
diff --git a/packages/synapse-react/package.json b/packages/synapse-react/package.json
index 8d1ceb67..707b1e91 100644
--- a/packages/synapse-react/package.json
+++ b/packages/synapse-react/package.json
@@ -51,6 +51,9 @@
],
"output": [
"dist/**"
+ ],
+ "dependencies": [
+ "../../packages/synapse-core:build"
]
},
"lint": {
diff --git a/packages/synapse-react/src/warm-storage/index.ts b/packages/synapse-react/src/warm-storage/index.ts
index 313a8a56..afe8eab1 100644
--- a/packages/synapse-react/src/warm-storage/index.ts
+++ b/packages/synapse-react/src/warm-storage/index.ts
@@ -1,5 +1,6 @@
export * from './use-create-data-set.ts'
export * from './use-data-sets.ts'
+export * from './use-delete-piece.ts'
export * from './use-providers.ts'
export * from './use-service-price.ts'
export * from './use-upload.ts'
diff --git a/packages/synapse-react/src/warm-storage/use-create-data-set.ts b/packages/synapse-react/src/warm-storage/use-create-data-set.ts
index 88bdd7c3..fd11b683 100644
--- a/packages/synapse-react/src/warm-storage/use-create-data-set.ts
+++ b/packages/synapse-react/src/warm-storage/use-create-data-set.ts
@@ -1,5 +1,5 @@
-import type { DataSetCreatedResponse } from '@filoz/synapse-core/curio'
-import * as Curio from '@filoz/synapse-core/curio'
+import type { DataSetCreatedResponse } from '@filoz/synapse-core/sp'
+import * as SP from '@filoz/synapse-core/sp'
import type { PDPProvider } from '@filoz/synapse-core/warm-storage'
import { createDataSet } from '@filoz/synapse-core/warm-storage'
import { type MutateOptions, useMutation, useQueryClient } from '@tanstack/react-query'
@@ -37,8 +37,7 @@ export function useCreateDataSet(props: UseCreateDataSetProps) {
chainId,
})
- const { hash, statusUrl } = await createDataSet(connectorClient, {
- publicClient: config.getClient(),
+ const { txHash, statusUrl } = await createDataSet(connectorClient, {
provider,
cdn,
// metadata: {
@@ -46,9 +45,9 @@ export function useCreateDataSet(props: UseCreateDataSetProps) {
// description: 'Test Description',
// },
})
- props?.onHash?.(hash)
+ props?.onHash?.(txHash)
- const dataSet = await Curio.pollForDataSetCreationStatus({ statusUrl })
+ const dataSet = await SP.pollForDataSetCreationStatus({ statusUrl })
queryClient.invalidateQueries({
queryKey: ['synapse-warm-storage-data-sets', account.address],
diff --git a/packages/synapse-react/src/warm-storage/use-data-sets.ts b/packages/synapse-react/src/warm-storage/use-data-sets.ts
index 9b1934f3..d15ef295 100644
--- a/packages/synapse-react/src/warm-storage/use-data-sets.ts
+++ b/packages/synapse-react/src/warm-storage/use-data-sets.ts
@@ -1,16 +1,13 @@
import { type MetadataObject, metadataArrayToObject } from '@filoz/synapse-core'
import { getChain } from '@filoz/synapse-core/chains'
-import type { CurioPieceWithUrl } from '@filoz/synapse-core/curio'
-import * as PDP from '@filoz/synapse-core/curio'
-import { type DataSet, getDataSets, readProviders } from '@filoz/synapse-core/warm-storage'
+import { type DataSet, getDataSets, getPieces, type Piece } from '@filoz/synapse-core/warm-storage'
import { skipToken, type UseQueryOptions, useQuery } from '@tanstack/react-query'
import type { Simplify } from 'type-fest'
import type { Address } from 'viem'
import { readContract } from 'viem/actions'
import { useChainId, useConfig } from 'wagmi'
-import { useProviders } from './use-providers.ts'
-export type PieceWithMetadata = Simplify
+export type PieceWithMetadata = Simplify
export interface DataSetWithPieces extends DataSet {
pieces: PieceWithMetadata[]
@@ -27,32 +24,26 @@ export function useDataSets(props: UseDataSetsProps) {
const config = useConfig()
const chainId = useChainId()
const address = props.address
- const { data: providersPrefected } = useProviders()
const chain = getChain(chainId)
return useQuery({
queryKey: ['synapse-warm-storage-data-sets', address],
queryFn: address
? async () => {
- const providers = providersPrefected ?? (await readProviders(config.getClient()))
const dataSets = await getDataSets(config.getClient(), { address })
const dataSetsWithPieces = await Promise.all(
dataSets.map(async (dataSet) => {
- // TODO: Get the active pieces from the PDP contract instead of the Curio API
- const pieces = await PDP.getPiecesForDataSet({
- endpoint: providers.find((p) => p.providerId === dataSet.providerId)?.pdp.serviceURL || '',
- dataSetId: dataSet.pdpDatasetId,
- chainId,
+ const piecesPaginated = await getPieces(config.getClient(), {
+ dataSet,
address,
- cdn: dataSet.cdn,
})
const piecesWithMetadata = await Promise.all(
- pieces.map(async (piece) => {
+ piecesPaginated.pieces.map(async (piece) => {
const metadata = await readContract(config.getClient(), {
address: chain.contracts.storageView.address,
abi: chain.contracts.storageView.abi,
functionName: 'getAllPieceMetadata',
- args: [dataSet.pdpDatasetId, BigInt(piece.pieceId)],
+ args: [dataSet.dataSetId, BigInt(piece.id)],
})
return {
...piece,
diff --git a/packages/synapse-react/src/warm-storage/use-delete-piece.ts b/packages/synapse-react/src/warm-storage/use-delete-piece.ts
new file mode 100644
index 00000000..a37c68ce
--- /dev/null
+++ b/packages/synapse-react/src/warm-storage/use-delete-piece.ts
@@ -0,0 +1,56 @@
+import { getChain } from '@filoz/synapse-core/chains'
+import type { SessionKey } from '@filoz/synapse-core/session-key'
+import { type DataSet, deletePiece, pollForDeletePieceStatus } from '@filoz/synapse-core/warm-storage'
+import { type MutateOptions, useMutation, useQueryClient } from '@tanstack/react-query'
+import type { TransactionReceipt } from 'viem'
+import { useAccount, useChainId, useConfig } from 'wagmi'
+import { getConnectorClient } from 'wagmi/actions'
+
+export interface UseDeletePieceProps {
+ /**
+ * The callback to call when the hash is available.
+ */
+ onHash?: (hash: string) => void
+ sessionKey?: SessionKey
+ mutation?: Omit, 'mutationFn'>
+}
+
+export interface UseDeletePieceVariables {
+ dataSet: DataSet
+ pieceId: bigint
+}
+export function useDeletePiece(props: UseDeletePieceProps) {
+ const config = useConfig()
+ const chainId = useChainId({ config })
+ const chain = getChain(chainId)
+ const account = useAccount({ config })
+ const queryClient = useQueryClient()
+ const client = config.getClient()
+
+ return useMutation({
+ ...props?.mutation,
+ mutationFn: async ({ dataSet, pieceId }: UseDeletePieceVariables) => {
+ let connectorClient = await getConnectorClient(config, {
+ account: account.address,
+ chainId,
+ })
+
+ if (props?.sessionKey && (await props?.sessionKey.isValid(connectorClient, 'SchedulePieceRemovals'))) {
+ connectorClient = props?.sessionKey.client(chain, client.transport)
+ }
+
+ const deletePieceRsp = await deletePiece(connectorClient, {
+ dataSet,
+ pieceId,
+ })
+
+ props?.onHash?.(deletePieceRsp.txHash)
+ const rsp = await pollForDeletePieceStatus(client, deletePieceRsp)
+
+ queryClient.invalidateQueries({
+ queryKey: ['synapse-warm-storage-data-sets', account.address],
+ })
+ return rsp
+ },
+ })
+}
diff --git a/packages/synapse-react/src/warm-storage/use-upload.ts b/packages/synapse-react/src/warm-storage/use-upload.ts
index 8ce4e136..19a472a7 100644
--- a/packages/synapse-react/src/warm-storage/use-upload.ts
+++ b/packages/synapse-react/src/warm-storage/use-upload.ts
@@ -1,7 +1,7 @@
import { getChain } from '@filoz/synapse-core/chains'
-import type { AddPiecesSuccess } from '@filoz/synapse-core/curio'
-import * as Curio from '@filoz/synapse-core/curio'
import type { SessionKey } from '@filoz/synapse-core/session-key'
+import type { AddPiecesSuccess } from '@filoz/synapse-core/sp'
+import * as SP from '@filoz/synapse-core/sp'
import { upload } from '@filoz/synapse-core/warm-storage'
import { type MutateOptions, useMutation, useQueryClient } from '@tanstack/react-query'
import { useAccount, useChainId, useConfig } from 'wagmi'
@@ -12,13 +12,13 @@ export interface UseUploadProps {
* The callback to call when the hash is available.
*/
onHash?: (hash: string) => void
+ sessionKey?: SessionKey
mutation?: Omit, 'mutationFn'>
}
export interface UseUploadVariables {
files: File[]
dataSetId: bigint
- sessionKey?: SessionKey
}
export function useUpload(props: UseUploadProps) {
const config = useConfig()
@@ -30,24 +30,22 @@ export function useUpload(props: UseUploadProps) {
return useMutation({
...props?.mutation,
- mutationFn: async ({ files, dataSetId, sessionKey }: UseUploadVariables) => {
+ mutationFn: async ({ files, dataSetId }: UseUploadVariables) => {
let connectorClient = await getConnectorClient(config, {
account: account.address,
chainId,
})
- if (sessionKey && (await sessionKey.isValid(connectorClient, 'AddPieces'))) {
- connectorClient = sessionKey.client(chain, client.transport)
+ if (props?.sessionKey && (await props?.sessionKey.isValid(connectorClient, 'AddPieces'))) {
+ connectorClient = props?.sessionKey.client(chain, client.transport)
}
- const pieces = await upload(connectorClient, {
+ const uploadRsp = await upload(connectorClient, {
dataSetId,
data: files,
})
- props?.onHash?.(pieces.txHash)
- const rsp = await Curio.pollForAddPiecesStatus({
- statusUrl: pieces.statusUrl,
- })
+ props?.onHash?.(uploadRsp.txHash)
+ const rsp = await SP.pollForAddPiecesStatus(uploadRsp)
queryClient.invalidateQueries({
queryKey: ['synapse-warm-storage-data-sets', account.address],
diff --git a/packages/synapse-sdk/package.json b/packages/synapse-sdk/package.json
index d3ab0af7..70cd8df8 100644
--- a/packages/synapse-sdk/package.json
+++ b/packages/synapse-sdk/package.json
@@ -1,6 +1,6 @@
{
"name": "@filoz/synapse-sdk",
- "version": "0.34.0",
+ "version": "0.35.0-dev.1",
"description": "JavaScript SDK for Filecoin Onchain Cloud",
"repository": {
"type": "git",
@@ -54,16 +54,71 @@
},
"scripts": {
"generate-abi": "wagmi generate",
- "build": "tsc --build",
- "lint": "tsc --build && biome check --no-errors-on-unmatched --files-ignore-unknown=true .",
+ "build": "wireit",
+ "lint": "wireit",
"lint:fix": "biome check --no-errors-on-unmatched --files-ignore-unknown=true --fix .",
- "test": "pnpm run lint && pnpm run test:node",
- "test:node": "playwright-test 'src/test/**/!(*.browser).test.ts' --mode node",
- "test:browser": "playwright-test 'src/test/**/!(*.node).test.ts' --assets ./src/test/mocks",
+ "test": "wireit",
+ "test:node": "wireit",
+ "test:browser": "wireit",
"clean": "rm -rf dist",
"prepublishOnly": "pnpm run clean && pnpm run build"
},
+ "wireit": {
+ "build": {
+ "command": "tsc --build --pretty",
+ "clean": "if-file-deleted",
+ "files": [
+ "src/**/*.ts",
+ "tsconfig.json"
+ ],
+ "output": [
+ "dist/**"
+ ]
+ },
+ "lint": {
+ "command": "biome check --no-errors-on-unmatched --files-ignore-unknown=true .",
+ "files": [
+ "src/**/*.ts",
+ "../../biome.json"
+ ],
+ "output": [],
+ "dependencies": [
+ "build"
+ ]
+ },
+ "test": {
+ "command": "pnpm run test:node && pnpm run test:browser",
+ "files": [
+ "src/**/*.ts"
+ ],
+ "output": [],
+ "dependencies": [
+ "lint"
+ ]
+ },
+ "test:node": {
+ "command": "playwright-test \"src/test/**/*.test.ts\" --mode node",
+ "files": [
+ "src/**/*.ts"
+ ],
+ "output": [],
+ "dependencies": [
+ "../synapse-core:build"
+ ]
+ },
+ "test:browser": {
+ "command": "playwright-test \"src/test/**/*.test.ts\" --assets ./src/test/mocks",
+ "files": [
+ "src/**/*.ts"
+ ],
+ "output": [],
+ "dependencies": [
+ "../synapse-core:build"
+ ]
+ }
+ },
"dependencies": {
+ "@filoz/synapse-core": "workspace:^",
"@web3-storage/data-segment": "^5.3.0",
"ethers": "^6.15.0",
"multiformats": "^13.4.1",
@@ -78,7 +133,7 @@
"@wagmi/cli": "^2.7.0",
"abitype": "^1.1.1",
"chai": "^6.2.0",
- "iso-web": "^1.4.0",
+ "iso-web": "^1.4.2",
"mocha": "^11.7.4",
"msw": "~2.10.5",
"p-defer": "^4.0.1",
diff --git a/packages/synapse-sdk/src/abis/gen.ts b/packages/synapse-sdk/src/abis/gen.ts
index 842a5882..07ebc0fb 100644
--- a/packages/synapse-sdk/src/abis/gen.ts
+++ b/packages/synapse-sdk/src/abis/gen.ts
@@ -16,9 +16,13 @@ export const filecoinWarmStorageServiceAbi = [
internalType: 'address',
type: 'address',
},
- { name: '_usdfcTokenAddress', internalType: 'address', type: 'address' },
{
- name: '_filCDNBeneficiaryAddress',
+ name: '_usdfc',
+ internalType: 'contract IERC20Metadata',
+ type: 'address',
+ },
+ {
+ name: '_filBeamBeneficiaryAddress',
internalType: 'address',
type: 'address',
},
@@ -56,6 +60,27 @@ export const filecoinWarmStorageServiceAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
+ {
+ type: 'function',
+ inputs: [
+ {
+ name: 'plannedUpgrade',
+ internalType: 'struct FilecoinWarmStorageService.PlannedUpgrade',
+ type: 'tuple',
+ components: [
+ {
+ name: 'nextImplementation',
+ internalType: 'address',
+ type: 'address',
+ },
+ { name: 'afterEpoch', internalType: 'uint96', type: 'uint96' },
+ ],
+ },
+ ],
+ name: 'announcePlannedUpgrade',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ },
{
type: 'function',
inputs: [{ name: 'totalBytes', internalType: 'uint256', type: 'uint256' }],
@@ -97,7 +122,7 @@ export const filecoinWarmStorageServiceAbi = [
inputs: [
{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
{ name: '', internalType: 'uint256', type: 'uint256' },
- { name: 'extraData', internalType: 'bytes', type: 'bytes' },
+ { name: '', internalType: 'bytes', type: 'bytes' },
],
name: 'dataSetDeleted',
outputs: [],
@@ -138,7 +163,7 @@ export const filecoinWarmStorageServiceAbi = [
{
type: 'function',
inputs: [],
- name: 'filCDNBeneficiaryAddress',
+ name: 'filBeamBeneficiaryAddress',
outputs: [{ name: '', internalType: 'address', type: 'address' }],
stateMutability: 'view',
},
@@ -182,7 +207,11 @@ export const filecoinWarmStorageServiceAbi = [
internalType: 'uint256',
type: 'uint256',
},
- { name: 'tokenAddress', internalType: 'address', type: 'address' },
+ {
+ name: 'tokenAddress',
+ internalType: 'contract IERC20',
+ type: 'address',
+ },
{ name: 'epochsPerMonth', internalType: 'uint256', type: 'uint256' },
],
},
@@ -199,7 +228,7 @@ export const filecoinWarmStorageServiceAbi = [
type: 'uint256',
},
{
- name: '_filCDNControllerAddress',
+ name: '_filBeamControllerAddress',
internalType: 'address',
type: 'address',
},
@@ -337,13 +366,6 @@ export const filecoinWarmStorageServiceAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
- {
- type: 'function',
- inputs: [],
- name: 'serviceCommissionBps',
- outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
- stateMutability: 'view',
- },
{
type: 'function',
inputs: [],
@@ -383,8 +405,19 @@ export const filecoinWarmStorageServiceAbi = [
type: 'function',
inputs: [
{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
- { name: 'oldServiceProvider', internalType: 'address', type: 'address' },
- { name: 'newServiceProvider', internalType: 'address', type: 'address' },
+ { name: 'cdnAmount', internalType: 'uint256', type: 'uint256' },
+ { name: 'cacheMissAmount', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'settleFilBeamPaymentRails',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: '', internalType: 'uint256', type: 'uint256' },
+ { name: '', internalType: 'address', type: 'address' },
+ { name: '', internalType: 'address', type: 'address' },
{ name: '', internalType: 'bytes', type: 'bytes' },
],
name: 'storageProviderChanged',
@@ -405,12 +438,27 @@ export const filecoinWarmStorageServiceAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
+ {
+ type: 'function',
+ inputs: [
+ { name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
+ { name: 'cdnAmountToAdd', internalType: 'uint256', type: 'uint256' },
+ {
+ name: 'cacheMissAmountToAdd',
+ internalType: 'uint256',
+ type: 'uint256',
+ },
+ ],
+ name: 'topUpCDNPaymentRails',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ },
{
type: 'function',
inputs: [
{ name: 'newController', internalType: 'address', type: 'address' },
],
- name: 'transferFilCDNController',
+ name: 'transferFilBeamController',
outputs: [],
stateMutability: 'nonpayable',
},
@@ -444,7 +492,9 @@ export const filecoinWarmStorageServiceAbi = [
type: 'function',
inputs: [],
name: 'usdfcTokenAddress',
- outputs: [{ name: '', internalType: 'address', type: 'address' }],
+ outputs: [
+ { name: '', internalType: 'contract IERC20Metadata', type: 'address' },
+ ],
stateMutability: 'view',
},
{
@@ -469,7 +519,7 @@ export const filecoinWarmStorageServiceAbi = [
],
},
],
- stateMutability: 'nonpayable',
+ stateMutability: 'view',
},
{
type: 'function',
@@ -478,6 +528,43 @@ export const filecoinWarmStorageServiceAbi = [
outputs: [{ name: '', internalType: 'address', type: 'address' }],
stateMutability: 'view',
},
+ {
+ type: 'event',
+ anonymous: false,
+ inputs: [
+ {
+ name: 'dataSetId',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: true,
+ },
+ {
+ name: 'cdnAmountAdded',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ {
+ name: 'totalCdnLockup',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ {
+ name: 'cacheMissAmountAdded',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ {
+ name: 'totalCacheMissLockup',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ ],
+ name: 'CDNPaymentRailsToppedUp',
+ },
{
type: 'event',
anonymous: false,
@@ -694,7 +781,7 @@ export const filecoinWarmStorageServiceAbi = [
indexed: false,
},
],
- name: 'FilCDNControllerChanged',
+ name: 'FilBeamControllerChanged',
},
{
type: 'event',
@@ -767,43 +854,6 @@ export const filecoinWarmStorageServiceAbi = [
],
name: 'PDPPaymentTerminated',
},
- {
- type: 'event',
- anonymous: false,
- inputs: [
- {
- name: 'railId',
- internalType: 'uint256',
- type: 'uint256',
- indexed: false,
- },
- {
- name: 'dataSetId',
- internalType: 'uint256',
- type: 'uint256',
- indexed: false,
- },
- {
- name: 'originalAmount',
- internalType: 'uint256',
- type: 'uint256',
- indexed: false,
- },
- {
- name: 'modifiedAmount',
- internalType: 'uint256',
- type: 'uint256',
- indexed: false,
- },
- {
- name: 'faultedEpochs',
- internalType: 'uint256',
- type: 'uint256',
- indexed: false,
- },
- ],
- name: 'PaymentArbitrated',
- },
{
type: 'event',
anonymous: false,
@@ -930,6 +980,27 @@ export const filecoinWarmStorageServiceAbi = [
],
name: 'ServiceTerminated',
},
+ {
+ type: 'event',
+ anonymous: false,
+ inputs: [
+ {
+ name: 'plannedUpgrade',
+ internalType: 'struct FilecoinWarmStorageService.PlannedUpgrade',
+ type: 'tuple',
+ components: [
+ {
+ name: 'nextImplementation',
+ internalType: 'address',
+ type: 'address',
+ },
+ { name: 'afterEpoch', internalType: 'uint96', type: 'uint96' },
+ ],
+ indexed: false,
+ },
+ ],
+ name: 'UpgradeAnnounced',
+ },
{
type: 'event',
anonymous: false,
@@ -961,6 +1032,25 @@ export const filecoinWarmStorageServiceAbi = [
inputs: [{ name: 'target', internalType: 'address', type: 'address' }],
name: 'AddressEmptyCode',
},
+ {
+ type: 'error',
+ inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
+ name: 'CDNPaymentAlreadyTerminated',
+ },
+ {
+ type: 'error',
+ inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
+ name: 'CacheMissPaymentAlreadyTerminated',
+ },
+ {
+ type: 'error',
+ inputs: [
+ { name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
+ { name: 'expectedPayer', internalType: 'address', type: 'address' },
+ { name: 'caller', internalType: 'address', type: 'address' },
+ ],
+ name: 'CallerNotPayer',
+ },
{
type: 'error',
inputs: [
@@ -988,6 +1078,13 @@ export const filecoinWarmStorageServiceAbi = [
],
name: 'ChallengeWindowTooEarly',
},
+ {
+ type: 'error',
+ inputs: [
+ { name: 'clientDataSetId', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'ClientDataSetAlreadyRegistered',
+ },
{
type: 'error',
inputs: [
@@ -1047,12 +1144,7 @@ export const filecoinWarmStorageServiceAbi = [
{
type: 'error',
inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
- name: 'FilCDNPaymentAlreadyTerminated',
- },
- {
- type: 'error',
- inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
- name: 'FilCDNServiceNotConfigured',
+ name: 'FilBeamServiceNotConfigured',
},
{
type: 'error',
@@ -1097,19 +1189,18 @@ export const filecoinWarmStorageServiceAbi = [
{ type: 'error', inputs: [], name: 'InvalidInitialization' },
{
type: 'error',
- inputs: [
- { name: 'expected', internalType: 'address', type: 'address' },
- { name: 'actual', internalType: 'address', type: 'address' },
- ],
- name: 'InvalidSignature',
+ inputs: [{ name: 'length', internalType: 'uint256', type: 'uint256' }],
+ name: 'InvalidServiceDescriptionLength',
},
{
type: 'error',
- inputs: [
- { name: 'expectedLength', internalType: 'uint256', type: 'uint256' },
- { name: 'actualLength', internalType: 'uint256', type: 'uint256' },
- ],
- name: 'InvalidSignatureLength',
+ inputs: [{ name: 'length', internalType: 'uint256', type: 'uint256' }],
+ name: 'InvalidServiceNameLength',
+ },
+ {
+ type: 'error',
+ inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
+ name: 'InvalidTopUpAmount',
},
{ type: 'error', inputs: [], name: 'MaxProvingPeriodZero' },
{
@@ -1164,19 +1255,10 @@ export const filecoinWarmStorageServiceAbi = [
{
type: 'error',
inputs: [
- { name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
{ name: 'expected', internalType: 'address', type: 'address' },
{ name: 'actual', internalType: 'address', type: 'address' },
],
- name: 'OldServiceProviderMismatch',
- },
- {
- type: 'error',
- inputs: [
- { name: 'expected', internalType: 'address', type: 'address' },
- { name: 'actual', internalType: 'address', type: 'address' },
- ],
- name: 'OnlyFilCDNControllerAllowed',
+ name: 'OnlyFilBeamControllerAllowed',
},
{
type: 'error',
@@ -1186,14 +1268,6 @@ export const filecoinWarmStorageServiceAbi = [
],
name: 'OnlyPDPVerifierAllowed',
},
- {
- type: 'error',
- inputs: [
- { name: 'expected', internalType: 'address', type: 'address' },
- { name: 'actual', internalType: 'address', type: 'address' },
- ],
- name: 'OnlySelf',
- },
{
type: 'error',
inputs: [{ name: 'owner', internalType: 'address', type: 'address' }],
@@ -1209,7 +1283,6 @@ export const filecoinWarmStorageServiceAbi = [
inputs: [
{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
{ name: 'pdpEndEpoch', internalType: 'uint256', type: 'uint256' },
- { name: 'cdnEndEpoch', internalType: 'uint256', type: 'uint256' },
],
name: 'PaymentRailsNotFinalized',
},
@@ -1223,14 +1296,6 @@ export const filecoinWarmStorageServiceAbi = [
inputs: [{ name: 'providerId', internalType: 'uint256', type: 'uint256' }],
name: 'ProviderAlreadyApproved',
},
- {
- type: 'error',
- inputs: [
- { name: 'provider', internalType: 'address', type: 'address' },
- { name: 'providerId', internalType: 'uint256', type: 'uint256' },
- ],
- name: 'ProviderNotApproved',
- },
{
type: 'error',
inputs: [{ name: 'providerId', internalType: 'uint256', type: 'uint256' }],
@@ -1275,11 +1340,6 @@ export const filecoinWarmStorageServiceAbi = [
inputs: [{ name: 'slot', internalType: 'bytes32', type: 'bytes32' }],
name: 'UUPSUnsupportedProxiableUUID',
},
- {
- type: 'error',
- inputs: [{ name: 'v', internalType: 'uint8', type: 'uint8' }],
- name: 'UnsupportedSignatureV',
- },
{
type: 'error',
inputs: [
@@ -1340,8 +1400,11 @@ export const filecoinWarmStorageServiceStateViewAbi = [
},
{
type: 'function',
- inputs: [{ name: 'payer', internalType: 'address', type: 'address' }],
- name: 'clientDataSetIDs',
+ inputs: [
+ { name: 'payer', internalType: 'address', type: 'address' },
+ { name: 'clientDataSetId', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'clientDataSetIds',
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
@@ -1357,7 +1420,7 @@ export const filecoinWarmStorageServiceStateViewAbi = [
{
type: 'function',
inputs: [],
- name: 'filCDNControllerAddress',
+ name: 'filBeamControllerAddress',
outputs: [{ name: '', internalType: 'address', type: 'address' }],
stateMutability: 'view',
},
@@ -1386,13 +1449,23 @@ export const filecoinWarmStorageServiceStateViewAbi = [
},
{
type: 'function',
- inputs: [],
+ inputs: [
+ { name: 'offset', internalType: 'uint256', type: 'uint256' },
+ { name: 'limit', internalType: 'uint256', type: 'uint256' },
+ ],
name: 'getApprovedProviders',
outputs: [
{ name: 'providerIds', internalType: 'uint256[]', type: 'uint256[]' },
],
stateMutability: 'view',
},
+ {
+ type: 'function',
+ inputs: [],
+ name: 'getApprovedProvidersLength',
+ outputs: [{ name: 'count', internalType: 'uint256', type: 'uint256' }],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [],
@@ -1407,7 +1480,7 @@ export const filecoinWarmStorageServiceStateViewAbi = [
outputs: [
{
name: 'infos',
- internalType: 'struct FilecoinWarmStorageService.DataSetInfo[]',
+ internalType: 'struct FilecoinWarmStorageService.DataSetInfoView[]',
type: 'tuple[]',
components: [
{ name: 'pdpRailId', internalType: 'uint256', type: 'uint256' },
@@ -1420,7 +1493,7 @@ export const filecoinWarmStorageServiceStateViewAbi = [
{ name: 'clientDataSetId', internalType: 'uint256', type: 'uint256' },
{ name: 'pdpEndEpoch', internalType: 'uint256', type: 'uint256' },
{ name: 'providerId', internalType: 'uint256', type: 'uint256' },
- { name: 'cdnEndEpoch', internalType: 'uint256', type: 'uint256' },
+ { name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
],
},
],
@@ -1433,7 +1506,7 @@ export const filecoinWarmStorageServiceStateViewAbi = [
outputs: [
{
name: 'info',
- internalType: 'struct FilecoinWarmStorageService.DataSetInfo',
+ internalType: 'struct FilecoinWarmStorageService.DataSetInfoView',
type: 'tuple',
components: [
{ name: 'pdpRailId', internalType: 'uint256', type: 'uint256' },
@@ -1446,7 +1519,7 @@ export const filecoinWarmStorageServiceStateViewAbi = [
{ name: 'clientDataSetId', internalType: 'uint256', type: 'uint256' },
{ name: 'pdpEndEpoch', internalType: 'uint256', type: 'uint256' },
{ name: 'providerId', internalType: 'uint256', type: 'uint256' },
- { name: 'cdnEndEpoch', internalType: 'uint256', type: 'uint256' },
+ { name: 'dataSetId', internalType: 'uint256', type: 'uint256' },
],
},
],
@@ -1472,6 +1545,19 @@ export const filecoinWarmStorageServiceStateViewAbi = [
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'pure',
},
+ {
+ type: 'function',
+ inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
+ name: 'getDataSetStatus',
+ outputs: [
+ {
+ name: 'status',
+ internalType: 'enum FilecoinWarmStorageService.DataSetStatus',
+ type: 'uint8',
+ },
+ ],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [],
@@ -1523,6 +1609,16 @@ export const filecoinWarmStorageServiceStateViewAbi = [
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
+ {
+ type: 'function',
+ inputs: [],
+ name: 'nextUpgrade',
+ outputs: [
+ { name: 'nextImplementation', internalType: 'address', type: 'address' },
+ { name: 'afterEpoch', internalType: 'uint96', type: 'uint96' },
+ ],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [
@@ -1574,6 +1670,13 @@ export const filecoinWarmStorageServiceStateViewAbi = [
],
stateMutability: 'view',
},
+ {
+ type: 'function',
+ inputs: [],
+ name: 'serviceCommissionBps',
+ outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
+ stateMutability: 'view',
+ },
{
type: 'error',
inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }],
@@ -1609,34 +1712,6 @@ export const filecoinWarmStorageServiceStateViewConfig = {
*/
export const pdpVerifierAbi = [
{ type: 'constructor', inputs: [], stateMutability: 'nonpayable' },
- {
- type: 'function',
- inputs: [],
- name: 'BURN_ACTOR',
- outputs: [{ name: '', internalType: 'address', type: 'address' }],
- stateMutability: 'view',
- },
- {
- type: 'function',
- inputs: [],
- name: 'EXTRA_DATA_MAX_SIZE',
- outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
- stateMutability: 'view',
- },
- {
- type: 'function',
- inputs: [],
- name: 'FIL_USD_PRICE_FEED_ID',
- outputs: [{ name: '', internalType: 'bytes32', type: 'bytes32' }],
- stateMutability: 'view',
- },
- {
- type: 'function',
- inputs: [],
- name: 'LEAF_SIZE',
- outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
- stateMutability: 'view',
- },
{
type: 'function',
inputs: [],
@@ -1665,27 +1740,6 @@ export const pdpVerifierAbi = [
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
- {
- type: 'function',
- inputs: [],
- name: 'PYTH',
- outputs: [{ name: '', internalType: 'contract IPyth', type: 'address' }],
- stateMutability: 'view',
- },
- {
- type: 'function',
- inputs: [],
- name: 'RANDOMNESS_PRECOMPILE',
- outputs: [{ name: '', internalType: 'address', type: 'address' }],
- stateMutability: 'view',
- },
- {
- type: 'function',
- inputs: [],
- name: 'SECONDS_IN_DAY',
- outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
- stateMutability: 'view',
- },
{
type: 'function',
inputs: [],
@@ -1704,6 +1758,7 @@ export const pdpVerifierAbi = [
type: 'function',
inputs: [
{ name: 'setId', internalType: 'uint256', type: 'uint256' },
+ { name: 'listenerAddr', internalType: 'address', type: 'address' },
{
name: 'pieceData',
internalType: 'struct Cids.Cid[]',
@@ -1714,18 +1769,22 @@ export const pdpVerifierAbi = [
],
name: 'addPieces',
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
- stateMutability: 'nonpayable',
+ stateMutability: 'payable',
},
{
type: 'function',
- inputs: [
- { name: 'setId', internalType: 'uint256', type: 'uint256' },
- { name: 'estimatedGasFee', internalType: 'uint256', type: 'uint256' },
- ],
+ inputs: [{ name: 'setId', internalType: 'uint256', type: 'uint256' }],
name: 'calculateProofFee',
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
+ {
+ type: 'function',
+ inputs: [{ name: 'proofSize', internalType: 'uint256', type: 'uint256' }],
+ name: 'calculateProofFeeForSize',
+ outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [
@@ -1763,6 +1822,20 @@ export const pdpVerifierAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
+ {
+ type: 'function',
+ inputs: [],
+ name: 'feeEffectiveTime',
+ outputs: [{ name: '', internalType: 'uint64', type: 'uint64' }],
+ stateMutability: 'view',
+ },
+ {
+ type: 'function',
+ inputs: [],
+ name: 'feePerTiB',
+ outputs: [{ name: '', internalType: 'uint96', type: 'uint96' }],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [
@@ -1808,7 +1881,6 @@ export const pdpVerifierAbi = [
components: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],
},
{ name: 'pieceIds', internalType: 'uint256[]', type: 'uint256[]' },
- { name: 'rawSizes', internalType: 'uint256[]', type: 'uint256[]' },
{ name: 'hasMore', internalType: 'bool', type: 'bool' },
],
stateMutability: 'view',
@@ -1858,16 +1930,6 @@ export const pdpVerifierAbi = [
],
stateMutability: 'view',
},
- {
- type: 'function',
- inputs: [],
- name: 'getFILUSDPrice',
- outputs: [
- { name: '', internalType: 'uint64', type: 'uint64' },
- { name: '', internalType: 'int32', type: 'int32' },
- ],
- stateMutability: 'view',
- },
{
type: 'function',
inputs: [{ name: 'setId', internalType: 'uint256', type: 'uint256' }],
@@ -1994,6 +2056,13 @@ export const pdpVerifierAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
+ {
+ type: 'function',
+ inputs: [],
+ name: 'proposedFeePerTiB',
+ outputs: [{ name: '', internalType: 'uint96', type: 'uint96' }],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [
@@ -2044,6 +2113,15 @@ export const pdpVerifierAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
+ {
+ type: 'function',
+ inputs: [
+ { name: 'newFeePerTiB', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'updateProofFee',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ },
{
type: 'function',
inputs: [
@@ -2124,6 +2202,31 @@ export const pdpVerifierAbi = [
],
name: 'DataSetEmpty',
},
+ {
+ type: 'event',
+ anonymous: false,
+ inputs: [
+ {
+ name: 'currentFee',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ {
+ name: 'newFee',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ {
+ name: 'effectiveTime',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ ],
+ name: 'FeeUpdateProposed',
+ },
{
type: 'event',
anonymous: false,
@@ -2260,8 +2363,6 @@ export const pdpVerifierAbi = [
indexed: true,
},
{ name: 'fee', internalType: 'uint256', type: 'uint256', indexed: false },
- { name: 'price', internalType: 'uint64', type: 'uint64', indexed: false },
- { name: 'expo', internalType: 'int32', type: 'int32', indexed: false },
],
name: 'ProofFeePaid',
},
@@ -2383,15 +2484,22 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [],
- name: 'NETWORK_FEE',
+ name: 'NETWORK_FEE_DENOMINATOR',
+ outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
+ stateMutability: 'view',
+ },
+ {
+ type: 'function',
+ inputs: [],
+ name: 'NETWORK_FEE_NUMERATOR',
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
{
type: 'function',
inputs: [
- { name: '', internalType: 'address', type: 'address' },
- { name: '', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'owner', internalType: 'address', type: 'address' },
],
name: 'accounts',
outputs: [
@@ -2405,7 +2513,30 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ ],
+ name: 'auctionInfo',
+ outputs: [
+ { name: 'startPrice', internalType: 'uint88', type: 'uint88' },
+ { name: 'startTime', internalType: 'uint168', type: 'uint168' },
+ ],
+ stateMutability: 'view',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'recipient', internalType: 'address', type: 'address' },
+ { name: 'requested', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'burnForFees',
+ outputs: [],
+ stateMutability: 'payable',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'validator', internalType: 'address', type: 'address' },
@@ -2419,18 +2550,84 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'to', internalType: 'address', type: 'address' },
+ { name: 'amount', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'deposit',
+ outputs: [],
+ stateMutability: 'payable',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: 'token', internalType: 'contract IERC3009', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
+ { name: 'validAfter', internalType: 'uint256', type: 'uint256' },
+ { name: 'validBefore', internalType: 'uint256', type: 'uint256' },
+ { name: 'nonce', internalType: 'bytes32', type: 'bytes32' },
+ { name: 'v', internalType: 'uint8', type: 'uint8' },
+ { name: 'r', internalType: 'bytes32', type: 'bytes32' },
+ { name: 's', internalType: 'bytes32', type: 'bytes32' },
+ ],
+ name: 'depositWithAuthorization',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: 'token', internalType: 'contract IERC3009', type: 'address' },
+ { name: 'to', internalType: 'address', type: 'address' },
+ { name: 'amount', internalType: 'uint256', type: 'uint256' },
+ { name: 'validAfter', internalType: 'uint256', type: 'uint256' },
+ { name: 'validBefore', internalType: 'uint256', type: 'uint256' },
+ { name: 'nonce', internalType: 'bytes32', type: 'bytes32' },
+ { name: 'v', internalType: 'uint8', type: 'uint8' },
+ { name: 'r', internalType: 'bytes32', type: 'bytes32' },
+ { name: 's', internalType: 'bytes32', type: 'bytes32' },
+ { name: 'operator', internalType: 'address', type: 'address' },
+ { name: 'rateAllowance', internalType: 'uint256', type: 'uint256' },
+ { name: 'lockupAllowance', internalType: 'uint256', type: 'uint256' },
+ { name: 'maxLockupPeriod', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'depositWithAuthorizationAndApproveOperator',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: 'token', internalType: 'contract IERC3009', type: 'address' },
+ { name: 'to', internalType: 'address', type: 'address' },
+ { name: 'amount', internalType: 'uint256', type: 'uint256' },
+ { name: 'validAfter', internalType: 'uint256', type: 'uint256' },
+ { name: 'validBefore', internalType: 'uint256', type: 'uint256' },
+ { name: 'nonce', internalType: 'bytes32', type: 'bytes32' },
+ { name: 'v', internalType: 'uint8', type: 'uint8' },
+ { name: 'r', internalType: 'bytes32', type: 'bytes32' },
+ { name: 's', internalType: 'bytes32', type: 'bytes32' },
+ { name: 'operator', internalType: 'address', type: 'address' },
+ {
+ name: 'rateAllowanceIncrease',
+ internalType: 'uint256',
+ type: 'uint256',
+ },
+ {
+ name: 'lockupAllowanceIncrease',
+ internalType: 'uint256',
+ type: 'uint256',
+ },
],
- name: 'deposit',
+ name: 'depositWithAuthorizationAndIncreaseOperatorApproval',
outputs: [],
- stateMutability: 'payable',
+ stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
{ name: 'deadline', internalType: 'uint256', type: 'uint256' },
@@ -2445,7 +2642,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
{ name: 'deadline', internalType: 'uint256', type: 'uint256' },
@@ -2464,7 +2661,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
{ name: 'deadline', internalType: 'uint256', type: 'uint256' },
@@ -2490,7 +2687,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'owner', internalType: 'address', type: 'address' },
],
name: 'getAccountInfoIfSettled',
@@ -2512,7 +2709,7 @@ export const paymentsAbi = [
internalType: 'struct Payments.RailView',
type: 'tuple',
components: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'operator', internalType: 'address', type: 'address' },
@@ -2541,12 +2738,14 @@ export const paymentsAbi = [
type: 'function',
inputs: [
{ name: 'payee', internalType: 'address', type: 'address' },
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'offset', internalType: 'uint256', type: 'uint256' },
+ { name: 'limit', internalType: 'uint256', type: 'uint256' },
],
name: 'getRailsForPayeeAndToken',
outputs: [
{
- name: '',
+ name: 'results',
internalType: 'struct Payments.RailInfo[]',
type: 'tuple[]',
components: [
@@ -2555,6 +2754,8 @@ export const paymentsAbi = [
{ name: 'endEpoch', internalType: 'uint256', type: 'uint256' },
],
},
+ { name: 'nextOffset', internalType: 'uint256', type: 'uint256' },
+ { name: 'total', internalType: 'uint256', type: 'uint256' },
],
stateMutability: 'view',
},
@@ -2562,12 +2763,14 @@ export const paymentsAbi = [
type: 'function',
inputs: [
{ name: 'payer', internalType: 'address', type: 'address' },
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'offset', internalType: 'uint256', type: 'uint256' },
+ { name: 'limit', internalType: 'uint256', type: 'uint256' },
],
name: 'getRailsForPayerAndToken',
outputs: [
{
- name: '',
+ name: 'results',
internalType: 'struct Payments.RailInfo[]',
type: 'tuple[]',
components: [
@@ -2576,6 +2779,8 @@ export const paymentsAbi = [
{ name: 'endEpoch', internalType: 'uint256', type: 'uint256' },
],
},
+ { name: 'nextOffset', internalType: 'uint256', type: 'uint256' },
+ { name: 'total', internalType: 'uint256', type: 'uint256' },
],
stateMutability: 'view',
},
@@ -2589,7 +2794,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'operator', internalType: 'address', type: 'address' },
{
name: 'rateAllowanceIncrease',
@@ -2631,9 +2836,9 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: '', internalType: 'address', type: 'address' },
- { name: '', internalType: 'address', type: 'address' },
- { name: '', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'client', internalType: 'address', type: 'address' },
+ { name: 'operator', internalType: 'address', type: 'address' },
],
name: 'operatorApprovals',
outputs: [
@@ -2649,7 +2854,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'operator', internalType: 'address', type: 'address' },
{ name: 'approved', internalType: 'bool', type: 'bool' },
{ name: 'rateAllowance', internalType: 'uint256', type: 'uint256' },
@@ -2675,10 +2880,11 @@ export const paymentsAbi = [
internalType: 'uint256',
type: 'uint256',
},
+ { name: 'totalNetworkFee', internalType: 'uint256', type: 'uint256' },
{ name: 'finalSettledEpoch', internalType: 'uint256', type: 'uint256' },
{ name: 'note', internalType: 'string', type: 'string' },
],
- stateMutability: 'payable',
+ stateMutability: 'nonpayable',
},
{
type: 'function',
@@ -2692,6 +2898,7 @@ export const paymentsAbi = [
internalType: 'uint256',
type: 'uint256',
},
+ { name: 'totalNetworkFee', internalType: 'uint256', type: 'uint256' },
{ name: 'finalSettledEpoch', internalType: 'uint256', type: 'uint256' },
{ name: 'note', internalType: 'string', type: 'string' },
],
@@ -2707,7 +2914,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
],
name: 'withdraw',
@@ -2717,7 +2924,7 @@ export const paymentsAbi = [
{
type: 'function',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'to', internalType: 'address', type: 'address' },
{ name: 'amount', internalType: 'uint256', type: 'uint256' },
],
@@ -2731,7 +2938,7 @@ export const paymentsAbi = [
inputs: [
{
name: 'token',
- internalType: 'address',
+ internalType: 'contract IERC20',
type: 'address',
indexed: true,
},
@@ -2768,7 +2975,7 @@ export const paymentsAbi = [
inputs: [
{
name: 'token',
- internalType: 'address',
+ internalType: 'contract IERC20',
type: 'address',
indexed: true,
},
@@ -2780,12 +2987,6 @@ export const paymentsAbi = [
type: 'uint256',
indexed: false,
},
- {
- name: 'usedPermit',
- internalType: 'bool',
- type: 'bool',
- indexed: false,
- },
],
name: 'DepositRecorded',
},
@@ -2795,7 +2996,7 @@ export const paymentsAbi = [
inputs: [
{
name: 'token',
- internalType: 'address',
+ internalType: 'contract IERC20',
type: 'address',
indexed: true,
},
@@ -2857,7 +3058,7 @@ export const paymentsAbi = [
},
{
name: 'token',
- internalType: 'address',
+ internalType: 'contract IERC20',
type: 'address',
indexed: false,
},
@@ -2960,6 +3161,12 @@ export const paymentsAbi = [
type: 'uint256',
indexed: false,
},
+ {
+ name: 'networkFee',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
],
name: 'RailOneTimePaymentProcessed',
},
@@ -3016,6 +3223,12 @@ export const paymentsAbi = [
type: 'uint256',
indexed: false,
},
+ {
+ name: 'networkFee',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
{
name: 'settledUpTo',
internalType: 'uint256',
@@ -3051,7 +3264,7 @@ export const paymentsAbi = [
inputs: [
{
name: 'token',
- internalType: 'address',
+ internalType: 'contract IERC20',
type: 'address',
indexed: true,
},
@@ -3104,7 +3317,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'oldLockup', internalType: 'uint256', type: 'uint256' },
{ name: 'currentLockup', internalType: 'uint256', type: 'uint256' },
@@ -3114,8 +3327,8 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
- { name: 'token', internalType: 'address', type: 'address' },
{ name: 'currentLockup', internalType: 'uint256', type: 'uint256' },
{ name: 'lockupReduction', internalType: 'uint256', type: 'uint256' },
],
@@ -3124,7 +3337,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'required', internalType: 'uint256', type: 'uint256' },
{ name: 'actual', internalType: 'uint256', type: 'uint256' },
@@ -3134,7 +3347,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'available', internalType: 'uint256', type: 'uint256' },
{ name: 'required', internalType: 'uint256', type: 'uint256' },
@@ -3144,7 +3357,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'available', internalType: 'uint256', type: 'uint256' },
{ name: 'required', internalType: 'uint256', type: 'uint256' },
@@ -3196,7 +3409,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'account', internalType: 'address', type: 'address' },
{ name: 'lockupCurrent', internalType: 'uint256', type: 'uint256' },
{ name: 'fundsCurrent', internalType: 'uint256', type: 'uint256' },
@@ -3206,7 +3419,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'actualLockupFixed', internalType: 'uint256', type: 'uint256' },
{
@@ -3221,7 +3434,7 @@ export const paymentsAbi = [
type: 'error',
inputs: [
{ name: 'railId', internalType: 'uint256', type: 'uint256' },
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'expectedLockup', internalType: 'uint256', type: 'uint256' },
{ name: 'actualLockup', internalType: 'uint256', type: 'uint256' },
@@ -3242,7 +3455,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'from', internalType: 'address', type: 'address' },
{ name: 'actualLockupPeriod', internalType: 'uint256', type: 'uint256' },
{
@@ -3256,7 +3469,7 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'token', internalType: 'address', type: 'address' },
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
{ name: 'operator', internalType: 'address', type: 'address' },
{ name: 'maxAllowedPeriod', internalType: 'uint256', type: 'uint256' },
{ name: 'requestedPeriod', internalType: 'uint256', type: 'uint256' },
@@ -3350,16 +3563,6 @@ export const paymentsAbi = [
],
name: 'OnlyRailOperatorAllowed',
},
- {
- type: 'error',
- inputs: [
- { name: 'expectedFrom', internalType: 'address', type: 'address' },
- { name: 'expectedOperator', internalType: 'address', type: 'address' },
- { name: 'expectedTo', internalType: 'address', type: 'address' },
- { name: 'caller', internalType: 'address', type: 'address' },
- ],
- name: 'OnlyRailParticipantAllowed',
- },
{
type: 'error',
inputs: [
@@ -3387,10 +3590,16 @@ export const paymentsAbi = [
{
type: 'error',
inputs: [
- { name: 'expected', internalType: 'address', type: 'address' },
- { name: 'actual', internalType: 'address', type: 'address' },
+ { name: 'x', internalType: 'uint256', type: 'uint256' },
+ { name: 'y', internalType: 'uint256', type: 'uint256' },
+ { name: 'denominator', internalType: 'uint256', type: 'uint256' },
],
- name: 'PermitRecipientMustBeMsgSender',
+ name: 'PRBMath_MulDiv_Overflow',
+ },
+ {
+ type: 'error',
+ inputs: [{ name: 'x', internalType: 'UD60x18', type: 'uint256' }],
+ name: 'PRBMath_UD60x18_Exp2_InputTooBig',
},
{
type: 'error',
@@ -3425,6 +3634,14 @@ export const paymentsAbi = [
inputs: [{ name: 'token', internalType: 'address', type: 'address' }],
name: 'SafeERC20FailedOperation',
},
+ {
+ type: 'error',
+ inputs: [
+ { name: 'expected', internalType: 'address', type: 'address' },
+ { name: 'actual', internalType: 'address', type: 'address' },
+ ],
+ name: 'SignerMustBeMsgSender',
+ },
{
type: 'error',
inputs: [
@@ -3452,6 +3669,15 @@ export const paymentsAbi = [
],
name: 'ValidatorSettledBeyondSegmentEnd',
},
+ {
+ type: 'error',
+ inputs: [
+ { name: 'token', internalType: 'contract IERC20', type: 'address' },
+ { name: 'available', internalType: 'uint256', type: 'uint256' },
+ { name: 'requested', internalType: 'uint256', type: 'uint256' },
+ ],
+ name: 'WithdrawAmountExceedsAccumulatedFees',
+ },
{
type: 'error',
inputs: [{ name: 'varName', internalType: 'string', type: 'string' }],
@@ -3487,13 +3713,6 @@ export const paymentsConfig = {
*/
export const serviceProviderRegistryAbi = [
{ type: 'constructor', inputs: [], stateMutability: 'nonpayable' },
- {
- type: 'function',
- inputs: [],
- name: 'BURN_ACTOR',
- outputs: [{ name: '', internalType: 'address', type: 'address' }],
- stateMutability: 'view',
- },
{
type: 'function',
inputs: [],
@@ -3581,50 +3800,6 @@ export const serviceProviderRegistryAbi = [
outputs: [{ name: 'providerId', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
- {
- type: 'function',
- inputs: [{ name: 'data', internalType: 'bytes', type: 'bytes' }],
- name: 'decodePDPOffering',
- outputs: [
- {
- name: '',
- internalType: 'struct ServiceProviderRegistryStorage.PDPOffering',
- type: 'tuple',
- components: [
- { name: 'serviceURL', internalType: 'string', type: 'string' },
- {
- name: 'minPieceSizeInBytes',
- internalType: 'uint256',
- type: 'uint256',
- },
- {
- name: 'maxPieceSizeInBytes',
- internalType: 'uint256',
- type: 'uint256',
- },
- { name: 'ipniPiece', internalType: 'bool', type: 'bool' },
- { name: 'ipniIpfs', internalType: 'bool', type: 'bool' },
- {
- name: 'storagePricePerTibPerMonth',
- internalType: 'uint256',
- type: 'uint256',
- },
- {
- name: 'minProvingPeriodInEpochs',
- internalType: 'uint256',
- type: 'uint256',
- },
- { name: 'location', internalType: 'string', type: 'string' },
- {
- name: 'paymentTokenAddress',
- internalType: 'contract IERC20',
- type: 'address',
- },
- ],
- },
- ],
- stateMutability: 'pure',
- },
{
type: 'function',
inputs: [],
@@ -3640,50 +3815,6 @@ export const serviceProviderRegistryAbi = [
],
stateMutability: 'view',
},
- {
- type: 'function',
- inputs: [
- {
- name: 'pdpOffering',
- internalType: 'struct ServiceProviderRegistryStorage.PDPOffering',
- type: 'tuple',
- components: [
- { name: 'serviceURL', internalType: 'string', type: 'string' },
- {
- name: 'minPieceSizeInBytes',
- internalType: 'uint256',
- type: 'uint256',
- },
- {
- name: 'maxPieceSizeInBytes',
- internalType: 'uint256',
- type: 'uint256',
- },
- { name: 'ipniPiece', internalType: 'bool', type: 'bool' },
- { name: 'ipniIpfs', internalType: 'bool', type: 'bool' },
- {
- name: 'storagePricePerTibPerMonth',
- internalType: 'uint256',
- type: 'uint256',
- },
- {
- name: 'minProvingPeriodInEpochs',
- internalType: 'uint256',
- type: 'uint256',
- },
- { name: 'location', internalType: 'string', type: 'string' },
- {
- name: 'paymentTokenAddress',
- internalType: 'contract IERC20',
- type: 'address',
- },
- ],
- },
- ],
- name: 'encodePDPOffering',
- outputs: [{ name: '', internalType: 'bytes', type: 'bytes' }],
- stateMutability: 'pure',
- },
{
type: 'function',
inputs: [
@@ -3729,11 +3860,6 @@ export const serviceProviderRegistryAbi = [
type: 'string',
},
{ name: 'isActive', internalType: 'bool', type: 'bool' },
- {
- name: 'providerId',
- internalType: 'uint256',
- type: 'uint256',
- },
],
},
{
@@ -3892,16 +4018,27 @@ export const serviceProviderRegistryAbi = [
outputs: [
{
name: 'info',
- internalType:
- 'struct ServiceProviderRegistryStorage.ServiceProviderInfo',
+ internalType: 'struct ServiceProviderRegistry.ServiceProviderInfoView',
type: 'tuple',
components: [
- { name: 'serviceProvider', internalType: 'address', type: 'address' },
- { name: 'payee', internalType: 'address', type: 'address' },
- { name: 'name', internalType: 'string', type: 'string' },
- { name: 'description', internalType: 'string', type: 'string' },
- { name: 'isActive', internalType: 'bool', type: 'bool' },
{ name: 'providerId', internalType: 'uint256', type: 'uint256' },
+ {
+ name: 'info',
+ internalType:
+ 'struct ServiceProviderRegistryStorage.ServiceProviderInfo',
+ type: 'tuple',
+ components: [
+ {
+ name: 'serviceProvider',
+ internalType: 'address',
+ type: 'address',
+ },
+ { name: 'payee', internalType: 'address', type: 'address' },
+ { name: 'name', internalType: 'string', type: 'string' },
+ { name: 'description', internalType: 'string', type: 'string' },
+ { name: 'isActive', internalType: 'bool', type: 'bool' },
+ ],
+ },
],
},
],
@@ -3916,16 +4053,27 @@ export const serviceProviderRegistryAbi = [
outputs: [
{
name: 'info',
- internalType:
- 'struct ServiceProviderRegistryStorage.ServiceProviderInfo',
+ internalType: 'struct ServiceProviderRegistry.ServiceProviderInfoView',
type: 'tuple',
components: [
- { name: 'serviceProvider', internalType: 'address', type: 'address' },
- { name: 'payee', internalType: 'address', type: 'address' },
- { name: 'name', internalType: 'string', type: 'string' },
- { name: 'description', internalType: 'string', type: 'string' },
- { name: 'isActive', internalType: 'bool', type: 'bool' },
{ name: 'providerId', internalType: 'uint256', type: 'uint256' },
+ {
+ name: 'info',
+ internalType:
+ 'struct ServiceProviderRegistryStorage.ServiceProviderInfo',
+ type: 'tuple',
+ components: [
+ {
+ name: 'serviceProvider',
+ internalType: 'address',
+ type: 'address',
+ },
+ { name: 'payee', internalType: 'address', type: 'address' },
+ { name: 'name', internalType: 'string', type: 'string' },
+ { name: 'description', internalType: 'string', type: 'string' },
+ { name: 'isActive', internalType: 'bool', type: 'bool' },
+ ],
+ },
],
},
],
@@ -3947,6 +4095,50 @@ export const serviceProviderRegistryAbi = [
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
+ {
+ type: 'function',
+ inputs: [{ name: 'providerId', internalType: 'uint256', type: 'uint256' }],
+ name: 'getProviderPayee',
+ outputs: [{ name: 'payee', internalType: 'address', type: 'address' }],
+ stateMutability: 'view',
+ },
+ {
+ type: 'function',
+ inputs: [
+ { name: 'providerIds', internalType: 'uint256[]', type: 'uint256[]' },
+ ],
+ name: 'getProvidersByIds',
+ outputs: [
+ {
+ name: 'providerInfos',
+ internalType:
+ 'struct ServiceProviderRegistry.ServiceProviderInfoView[]',
+ type: 'tuple[]',
+ components: [
+ { name: 'providerId', internalType: 'uint256', type: 'uint256' },
+ {
+ name: 'info',
+ internalType:
+ 'struct ServiceProviderRegistryStorage.ServiceProviderInfo',
+ type: 'tuple',
+ components: [
+ {
+ name: 'serviceProvider',
+ internalType: 'address',
+ type: 'address',
+ },
+ { name: 'payee', internalType: 'address', type: 'address' },
+ { name: 'name', internalType: 'string', type: 'string' },
+ { name: 'description', internalType: 'string', type: 'string' },
+ { name: 'isActive', internalType: 'bool', type: 'bool' },
+ ],
+ },
+ ],
+ },
+ { name: 'validIds', internalType: 'bool[]', type: 'bool[]' },
+ ],
+ stateMutability: 'view',
+ },
{
type: 'function',
inputs: [
@@ -3992,11 +4184,6 @@ export const serviceProviderRegistryAbi = [
type: 'string',
},
{ name: 'isActive', internalType: 'bool', type: 'bool' },
- {
- name: 'providerId',
- internalType: 'uint256',
- type: 'uint256',
- },
],
},
{
@@ -4137,7 +4324,6 @@ export const serviceProviderRegistryAbi = [
{ name: 'name', internalType: 'string', type: 'string' },
{ name: 'description', internalType: 'string', type: 'string' },
{ name: 'isActive', internalType: 'bool', type: 'bool' },
- { name: 'providerId', internalType: 'uint256', type: 'uint256' },
],
stateMutability: 'view',
},
@@ -4351,18 +4537,18 @@ export const serviceProviderRegistryAbi = [
type: 'uint8',
indexed: true,
},
- {
- name: 'serviceUrl',
- internalType: 'string',
- type: 'string',
- indexed: false,
- },
{
name: 'serviceProvider',
internalType: 'address',
type: 'address',
indexed: false,
},
+ {
+ name: 'productData',
+ internalType: 'bytes',
+ type: 'bytes',
+ indexed: false,
+ },
{
name: 'capabilityKeys',
internalType: 'string[]',
@@ -4413,18 +4599,18 @@ export const serviceProviderRegistryAbi = [
type: 'uint8',
indexed: true,
},
- {
- name: 'serviceUrl',
- internalType: 'string',
- type: 'string',
- indexed: false,
- },
{
name: 'serviceProvider',
internalType: 'address',
type: 'address',
indexed: false,
},
+ {
+ name: 'productData',
+ internalType: 'bytes',
+ type: 'bytes',
+ indexed: false,
+ },
{
name: 'capabilityKeys',
internalType: 'string[]',
@@ -4582,6 +4768,7 @@ export const sessionKeyRegistryAbi = [
{ name: 'signer', internalType: 'address', type: 'address' },
{ name: 'expiry', internalType: 'uint256', type: 'uint256' },
{ name: 'permissions', internalType: 'bytes32[]', type: 'bytes32[]' },
+ { name: 'origin', internalType: 'string', type: 'string' },
],
name: 'login',
outputs: [],
@@ -4593,6 +4780,7 @@ export const sessionKeyRegistryAbi = [
{ name: 'signer', internalType: 'address payable', type: 'address' },
{ name: 'expiry', internalType: 'uint256', type: 'uint256' },
{ name: 'permissions', internalType: 'bytes32[]', type: 'bytes32[]' },
+ { name: 'origin', internalType: 'string', type: 'string' },
],
name: 'loginAndFund',
outputs: [],
@@ -4603,11 +4791,49 @@ export const sessionKeyRegistryAbi = [
inputs: [
{ name: 'signer', internalType: 'address', type: 'address' },
{ name: 'permissions', internalType: 'bytes32[]', type: 'bytes32[]' },
+ { name: 'origin', internalType: 'string', type: 'string' },
],
name: 'revoke',
outputs: [],
stateMutability: 'nonpayable',
},
+ {
+ type: 'event',
+ anonymous: false,
+ inputs: [
+ {
+ name: 'identity',
+ internalType: 'address',
+ type: 'address',
+ indexed: true,
+ },
+ {
+ name: 'signer',
+ internalType: 'address',
+ type: 'address',
+ indexed: false,
+ },
+ {
+ name: 'expiry',
+ internalType: 'uint256',
+ type: 'uint256',
+ indexed: false,
+ },
+ {
+ name: 'permissions',
+ internalType: 'bytes32[]',
+ type: 'bytes32[]',
+ indexed: false,
+ },
+ {
+ name: 'origin',
+ internalType: 'string',
+ type: 'string',
+ indexed: false,
+ },
+ ],
+ name: 'AuthorizationsUpdated',
+ },
] as const
/**
diff --git a/packages/synapse-sdk/src/payments/service.ts b/packages/synapse-sdk/src/payments/service.ts
index 0ad70340..13145da0 100644
--- a/packages/synapse-sdk/src/payments/service.ts
+++ b/packages/synapse-sdk/src/payments/service.ts
@@ -922,16 +922,15 @@ export class PaymentsService {
try {
// Use staticCall to simulate the transaction and get the return values
// Include the settlement fee (NETWORK_FEE in contract) in the simulation
- const result = await paymentsContract.settleRail.staticCall(railIdBigint, untilEpochBigint, {
- value: SETTLEMENT_FEE,
- })
+ const result = await paymentsContract.settleRail.staticCall(railIdBigint, untilEpochBigint)
return {
totalSettledAmount: result[0],
totalNetPayeeAmount: result[1],
totalOperatorCommission: result[2],
- finalSettledEpoch: result[3],
- note: result[4],
+ totalNetworkFee: result[3],
+ finalSettledEpoch: result[4],
+ note: result[5],
}
} catch (error) {
throw createError(
@@ -1078,7 +1077,7 @@ export class PaymentsService {
const paymentsContract = this._getPaymentsContract()
try {
- const rails = await paymentsContract.getRailsForPayerAndToken(signerAddress, this._usdfcAddress)
+ const [rails] = await paymentsContract.getRailsForPayerAndToken(signerAddress, this._usdfcAddress, 0n, 0n)
return rails.map((rail: any) => ({
railId: Number(rail.railId),
@@ -1108,7 +1107,7 @@ export class PaymentsService {
const paymentsContract = this._getPaymentsContract()
try {
- const rails = await paymentsContract.getRailsForPayeeAndToken(signerAddress, this._usdfcAddress)
+ const [rails] = await paymentsContract.getRailsForPayeeAndToken(signerAddress, this._usdfcAddress, 0n, 0n)
return rails.map((rail: any) => ({
railId: Number(rail.railId),
diff --git a/packages/synapse-sdk/src/pdp/auth.ts b/packages/synapse-sdk/src/pdp/auth.ts
index f38b1ecc..e9d824e9 100644
--- a/packages/synapse-sdk/src/pdp/auth.ts
+++ b/packages/synapse-sdk/src/pdp/auth.ts
@@ -204,7 +204,7 @@ export class PDPAuthHelper {
* ```
*/
async signCreateDataSet(
- clientDataSetId: number | bigint,
+ clientDataSetId: bigint,
payee: string,
metadata: MetadataEntry[] = []
): Promise {
@@ -226,7 +226,7 @@ export class PDPAuthHelper {
} else {
// Use standard ethers.js signing (for private keys, etc)
const value = {
- clientDataSetId: BigInt(clientDataSetId),
+ clientDataSetId,
metadata,
payee,
}
@@ -241,7 +241,7 @@ export class PDPAuthHelper {
// For EIP-712, signedData contains the actual message hash that was signed
const signedData = ethers.TypedDataEncoder.hash(this.domain, types, {
- clientDataSetId: BigInt(clientDataSetId),
+ clientDataSetId,
metadata,
payee,
})
@@ -282,8 +282,8 @@ export class PDPAuthHelper {
* ```
*/
async signAddPieces(
- clientDataSetId: number | bigint,
- firstPieceId: number | bigint,
+ clientDataSetId: bigint,
+ firstPieceId: bigint,
pieceDataArray: PieceCID[] | string[],
metadata: MetadataEntry[][] = []
): Promise {
@@ -341,8 +341,8 @@ export class PDPAuthHelper {
} else {
// Use standard ethers.js signing with bigint values
const value = {
- clientDataSetId: BigInt(clientDataSetId),
- firstAdded: BigInt(firstPieceId),
+ clientDataSetId,
+ firstAdded: firstPieceId,
pieceData: formattedPieceData,
pieceMetadata: pieceMetadata,
}
@@ -357,8 +357,8 @@ export class PDPAuthHelper {
// For EIP-712, signedData contains the actual message hash that was signed
const signedData = ethers.TypedDataEncoder.hash(this.domain, types, {
- clientDataSetId: BigInt(clientDataSetId),
- firstAdded: BigInt(firstPieceId),
+ clientDataSetId,
+ firstAdded: firstPieceId,
pieceData: formattedPieceData,
pieceMetadata: pieceMetadata,
})
@@ -392,13 +392,7 @@ export class PDPAuthHelper {
* )
* ```
*/
- async signSchedulePieceRemovals(
- clientDataSetId: number | bigint,
- pieceIds: Array
- ): Promise {
- // Convert pieceIds to BigInt array for proper encoding
- const pieceIdsBigInt = pieceIds.map((id) => BigInt(id))
-
+ async signSchedulePieceRemovals(clientDataSetId: bigint, pieceIds: Array): Promise {
let signature: string
// Check if we should use MetaMask-friendly signing
@@ -408,16 +402,13 @@ export class PDPAuthHelper {
// Use MetaMask-friendly signing for better UX
const value = {
clientDataSetId: clientDataSetId.toString(), // Keep as string for MetaMask display
- pieceIds: pieceIdsBigInt.map((id) => id.toString()), // Convert to string array for display
+ pieceIds: pieceIds.map((id) => id.toString()), // Convert to string array for display
}
signature = await this.signWithMetaMask({ SchedulePieceRemovals: EIP712_TYPES.SchedulePieceRemovals }, value)
} else {
// Use standard ethers.js signing with BigInt values
- const value = {
- clientDataSetId: BigInt(clientDataSetId),
- pieceIds: pieceIdsBigInt,
- }
+ const value = { clientDataSetId, pieceIds }
// Use underlying signer for typed data signing (handles NonceManager)
const actualSigner = this.getUnderlyingSigner()
@@ -434,10 +425,7 @@ export class PDPAuthHelper {
const signedData = ethers.TypedDataEncoder.hash(
this.domain,
{ SchedulePieceRemovals: EIP712_TYPES.SchedulePieceRemovals },
- {
- clientDataSetId: BigInt(clientDataSetId),
- pieceIds: pieceIdsBigInt,
- }
+ { clientDataSetId, pieceIds }
)
return {
@@ -467,7 +455,7 @@ export class PDPAuthHelper {
* )
* ```
*/
- async signDeleteDataSet(clientDataSetId: number | bigint): Promise {
+ async signDeleteDataSet(clientDataSetId: bigint): Promise {
let signature: string
// Check if we should use MetaMask-friendly signing
@@ -482,9 +470,7 @@ export class PDPAuthHelper {
signature = await this.signWithMetaMask({ DeleteDataSet: EIP712_TYPES.DeleteDataSet }, value)
} else {
// Use standard ethers.js signing
- const value = {
- clientDataSetId: BigInt(clientDataSetId),
- }
+ const value = { clientDataSetId }
// Use underlying signer for typed data signing (handles NonceManager)
const actualSigner = this.getUnderlyingSigner()
@@ -497,9 +483,7 @@ export class PDPAuthHelper {
const signedData = ethers.TypedDataEncoder.hash(
this.domain,
{ DeleteDataSet: EIP712_TYPES.DeleteDataSet },
- {
- clientDataSetId: BigInt(clientDataSetId),
- }
+ { clientDataSetId }
)
return {
diff --git a/packages/synapse-sdk/src/pdp/server.ts b/packages/synapse-sdk/src/pdp/server.ts
index 3b6e3985..9bdedcb7 100644
--- a/packages/synapse-sdk/src/pdp/server.ts
+++ b/packages/synapse-sdk/src/pdp/server.ts
@@ -26,18 +26,18 @@
* ```
*/
+import * as Piece from '@filoz/synapse-core/piece'
+import * as SP from '@filoz/synapse-core/sp'
import { ethers } from 'ethers'
-import { asPieceCID, calculate as calculatePieceCID, downloadAndValidate } from '../piece/index.ts'
+import type { Hex } from 'viem'
+import { asPieceCID, downloadAndValidate } from '../piece/index.ts'
import type { DataSetData, MetadataEntry, PieceCID } from '../types.ts'
import { validateDataSetMetadata, validatePieceMetadata } from '../utils/metadata.ts'
-import { constructFindPieceUrl, constructPieceUrl } from '../utils/piece.ts'
+import { constructPieceUrl } from '../utils/piece.ts'
import type { PDPAuthHelper } from './auth.ts'
import {
- asDataSetData,
validateDataSetCreationStatusResponse,
- validateFindPieceResponse,
validatePieceAdditionStatusResponse,
- validatePieceDeleteResponse,
validatePieceStatusResponse,
} from './validation.ts'
@@ -87,8 +87,6 @@ export interface AddPiecesResponse {
export interface FindPieceResponse {
/** The piece CID that was found */
pieceCid: PieceCID
- /** @deprecated Use pieceCid instead. This field is for backward compatibility and will be removed in a future version */
- piece_cid?: string
}
/**
@@ -146,12 +144,20 @@ export interface PieceAdditionStatusResponse {
* Input for adding pieces to a data set
*/
export interface PDPAddPiecesInput {
- pieces: {
- pieceCid: string
- subPieces: {
- subPieceCid: string
- }[]
+ pieces: PDPPieces[]
+ extraData: string
+}
+
+export interface PDPPieces {
+ pieceCid: string
+ subPieces: {
+ subPieceCid: string
}[]
+}
+
+export interface PDPCreateAndAddInput {
+ recordKeeper: string
+ pieces: PDPPieces[]
extraData: string
}
@@ -177,12 +183,13 @@ export class PDPServer {
* Create a new data set on the PDP server
* @param clientDataSetId - Unique ID for the client's dataset
* @param payee - Address that will receive payments (service provider)
+ * @param payer - Address that will pay for the storage (client)
* @param metadata - Metadata entries for the data set (key-value pairs)
* @param recordKeeper - Address of the Warm Storage contract
* @returns Promise that resolves with transaction hash and status URL
*/
async createDataSet(
- clientDataSetId: number,
+ clientDataSetId: bigint,
payee: string,
payer: string,
metadata: MetadataEntry[],
@@ -198,23 +205,87 @@ export class PDPServer {
// This needs to match the DataSetCreateData struct in Warm Storage contract
const extraData = this._encodeDataSetCreateData({
payer,
+ clientDataSetId,
metadata,
signature: authData.signature,
})
- // Prepare request body
- const requestBody = {
- recordKeeper,
+ return SP.createDataSet({
+ endpoint: this._serviceURL,
+ recordKeeper: recordKeeper as Hex,
extraData: `0x${extraData}`,
+ })
+ }
+
+ /**
+ * Creates a data set and adds pieces to it in a combined operation.
+ * Users can poll the status of the operation using the returned data set status URL.
+ * After which the user can use the returned transaction hash and data set ID to check the status of the piece addition.
+ * @param clientDataSetId - Unique ID for the client's dataset
+ * @param payee - Address that will receive payments (service provider)
+ * @param payer - Address that will pay for the storage (client)
+ * @param recordKeeper - Address of the Warm Storage contract
+ * @param pieceDataArray - Array of piece data containing PieceCID CIDs and raw sizes
+ * @param metadata - Optional metadata for dataset and each of the pieces.
+ * @returns Promise that resolves with transaction hash and status URL
+ */
+ async createAndAddPieces(
+ clientDataSetId: bigint,
+ payee: string,
+ payer: string,
+ recordKeeper: string,
+ pieceDataArray: PieceCID[] | string[],
+ metadata: {
+ dataset?: MetadataEntry[]
+ pieces?: MetadataEntry[][]
+ }
+ ): Promise {
+ // Validate metadata against contract limits
+ if (metadata.dataset == null) {
+ metadata.dataset = []
}
+ validateDataSetMetadata(metadata.dataset)
+ metadata.pieces = PDPServer._processAddPiecesInputs(pieceDataArray, metadata.pieces)
+
+ // Generate the EIP-712 signature for data set creation
+ const createAuthData = await this.getAuthHelper().signCreateDataSet(clientDataSetId, payee, metadata.dataset)
- // Make the POST request to create the data set
- const response = await fetch(`${this._serviceURL}/pdp/data-sets`, {
+ // Prepare the extra data for the contract call
+ // This needs to match the DataSetCreateData struct in Warm Storage contract
+ const createExtraData = this._encodeDataSetCreateData({
+ payer,
+ clientDataSetId,
+ metadata: metadata.dataset,
+ signature: createAuthData.signature,
+ })
+
+ const addAuthData = await this.getAuthHelper().signAddPieces(
+ clientDataSetId,
+ BigInt(0),
+ pieceDataArray, // Pass PieceData[] directly to auth helper
+ metadata.pieces
+ )
+
+ const addExtraData = this._encodeAddPiecesExtraData({
+ signature: addAuthData.signature,
+ metadata: metadata.pieces,
+ })
+
+ const abiCoder = ethers.AbiCoder.defaultAbiCoder()
+ const encoded = abiCoder.encode(['bytes', 'bytes'], [`0x${createExtraData}`, `0x${addExtraData}`])
+ const requestJson: PDPCreateAndAddInput = {
+ recordKeeper: recordKeeper,
+ pieces: PDPServer._formatPieceDataArrayForCurio(pieceDataArray),
+ extraData: `${encoded}`,
+ }
+
+ // Make the POST request to add pieces to the data set
+ const response = await fetch(`${this._serviceURL}/pdp/data-sets/create-and-add`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
- body: JSON.stringify(requestBody),
+ body: JSON.stringify(requestJson),
})
if (response.status !== 201) {
@@ -243,37 +314,18 @@ export class PDPServer {
}
}
- /**
- * Add pieces to an existing data set
- * @param dataSetId - The ID of the data set to add pieces to
- * @param clientDataSetId - The client's dataset ID used when creating the data set
- * @param nextPieceId - The ID to assign to the first piece being added, this should be
- * the next available ID on chain or the signature will fail to be validated
- * @param pieceDataArray - Array of piece data containing PieceCID CIDs and raw sizes
- * @param metadata - Optional metadata for each piece (array of arrays, one per piece)
- * @returns Promise that resolves when the pieces are added (201 Created)
- * @throws Error if any CID is invalid
- *
- * @example
- * ```typescript
- * const pieceData = ['bafkzcibcd...']
- * const metadata = [[{ key: 'snapshotDate', value: '20250711' }]]
- * await pdpTool.addPieces(dataSetId, clientDataSetId, nextPieceId, pieceData, metadata)
- * ```
- */
- async addPieces(
- dataSetId: number,
- clientDataSetId: number,
- nextPieceId: number,
+ private static _processAddPiecesInputs(
pieceDataArray: PieceCID[] | string[],
metadata?: MetadataEntry[][]
- ): Promise {
+ ): MetadataEntry[][] {
if (pieceDataArray.length === 0) {
throw new Error('At least one piece must be provided')
}
- // Validate piece metadata against contract limits
if (metadata != null) {
+ if (metadata.length !== pieceDataArray.length) {
+ throw new Error(`Metadata length (${metadata.length}) must match pieces length (${pieceDataArray.length})`)
+ }
for (let i = 0; i < metadata.length; i++) {
if (metadata[i] != null && metadata[i].length > 0) {
try {
@@ -292,19 +344,56 @@ export class PDPServer {
throw new Error(`Invalid PieceCID: ${String(pieceData)}`)
}
}
-
// If no metadata provided, create empty arrays for each piece
const finalMetadata = metadata ?? pieceDataArray.map(() => [])
+ return finalMetadata
+ }
- // Validate metadata length matches pieces
- if (finalMetadata.length !== pieceDataArray.length) {
- throw new Error(`Metadata length (${finalMetadata.length}) must match pieces length (${pieceDataArray.length})`)
- }
+ private static _formatPieceDataArrayForCurio(pieceDataArray: PieceCID[] | string[]): PDPPieces[] {
+ return pieceDataArray.map((pieceData) => {
+ // Convert to string for JSON serialization
+ const cidString = typeof pieceData === 'string' ? pieceData : pieceData.toString()
+ return {
+ pieceCid: cidString,
+ subPieces: [
+ {
+ subPieceCid: cidString, // Piece is its own subpiece
+ },
+ ],
+ }
+ })
+ }
+ /**
+ * Add pieces to an existing data set
+ * @param dataSetId - The ID of the data set to add pieces to
+ * @param clientDataSetId - The client's dataset ID used when creating the data set
+ * @param nextPieceId - The ID to assign to the first piece being added, this should be
+ * the next available ID on chain or the signature will fail to be validated
+ * @param pieceDataArray - Array of piece data containing PieceCID CIDs and raw sizes
+ * @param metadata - Optional metadata for each piece (array of arrays, one per piece)
+ * @returns Promise that resolves when the pieces are added (201 Created)
+ * @throws Error if any CID is invalid
+ *
+ * @example
+ * ```typescript
+ * const pieceData = ['bafkzcibcd...']
+ * const metadata = [[{ key: 'snapshotDate', value: '20250711' }]]
+ * await pdpTool.addPieces(dataSetId, clientDataSetId, nextPieceId, pieceData, metadata)
+ * ```
+ */
+ async addPieces(
+ dataSetId: number,
+ clientDataSetId: bigint,
+ nextPieceId: number,
+ pieceDataArray: PieceCID[] | string[],
+ metadata?: MetadataEntry[][]
+ ): Promise {
+ const finalMetadata = PDPServer._processAddPiecesInputs(pieceDataArray, metadata)
// Generate the EIP-712 signature for adding pieces
const authData = await this.getAuthHelper().signAddPieces(
clientDataSetId,
- nextPieceId,
+ BigInt(nextPieceId),
pieceDataArray, // Pass PieceData[] directly to auth helper
finalMetadata
)
@@ -316,60 +405,15 @@ export class PDPServer {
metadata: finalMetadata,
})
- // Prepare request body matching the Curio handler expectation
- // Each piece has itself as its only subPiece (internal implementation detail)
- const requestBody: PDPAddPiecesInput = {
- pieces: pieceDataArray.map((pieceData) => {
- // Convert to string for JSON serialization
- const cidString = typeof pieceData === 'string' ? pieceData : pieceData.toString()
- return {
- pieceCid: cidString,
- subPieces: [
- {
- subPieceCid: cidString, // Piece is its own subpiece
- },
- ],
- }
- }),
+ const { txHash, statusUrl } = await SP.addPieces({
+ endpoint: this._serviceURL,
+ dataSetId: BigInt(dataSetId),
+ pieces: pieceDataArray.map(asPieceCID).filter((t) => t != null),
extraData: `0x${extraData}`,
- }
-
- // Make the POST request to add pieces to the data set
- const response = await fetch(`${this._serviceURL}/pdp/data-sets/${dataSetId}/pieces`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(requestBody),
+ nextPieceId: BigInt(nextPieceId),
})
-
- if (response.status !== 201) {
- const errorText = await response.text()
- throw new Error(`Failed to add pieces to data set: ${response.status} ${response.statusText} - ${errorText}`)
- }
-
- // Check for Location header (backward compatible with old servers)
- const location = response.headers.get('Location')
- let txHash: string | undefined
- let statusUrl: string | undefined
-
- if (location != null) {
- // Expected format: /pdp/data-sets/{dataSetId}/pieces/added/{txHash}
- const locationMatch = location.match(/\/pieces\/added\/([0-9a-fA-Fx]+)$/)
- if (locationMatch != null) {
- txHash = locationMatch[1]
- // Ensure txHash has 0x prefix
- if (!txHash.startsWith('0x')) {
- txHash = `0x${txHash}`
- }
- statusUrl = `${this._serviceURL}${location}`
- }
- }
-
- // Success - pieces have been added
- const responseText = await response.text()
return {
- message: responseText !== '' ? responseText : `Pieces added to data set ID ${dataSetId} successfully`,
+ message: `Pieces added to data set ID ${dataSetId} successfully`,
txHash,
statusUrl,
}
@@ -441,27 +485,20 @@ export class PDPServer {
throw new Error(`Invalid PieceCID: ${String(pieceCid)}`)
}
- const url = constructFindPieceUrl(this._serviceURL, parsedPieceCid)
- const response = await fetch(url, {
- method: 'GET',
- headers: {},
+ const piece = await SP.findPiece({
+ endpoint: this._serviceURL,
+ pieceCid: parsedPieceCid,
})
-
- if (response.status === 404) {
- throw new Error(`Piece not found: ${parsedPieceCid.toString()}`)
- }
-
- if (!response.ok) {
- const errorText = await response.text()
- throw new Error(`Failed to find piece: ${response.status} ${response.statusText} - ${errorText}`)
+ return {
+ pieceCid: piece,
}
-
- const data = await response.json()
- return validateFindPieceResponse(data)
}
/**
* Get indexing and IPNI status for a piece
+ *
+ * TODO: not used anywhere, remove?
+ *
* @param pieceCid - The PieceCID CID (as string or PieceCID object)
* @returns Piece status information including indexing and IPNI advertisement status
* @throws Error if piece not found or doesn't belong to service (404)
@@ -502,87 +539,10 @@ export class PDPServer {
// Convert ArrayBuffer to Uint8Array if needed
const uint8Data = data instanceof ArrayBuffer ? new Uint8Array(data) : data
- // Calculate PieceCID
- performance.mark('synapse:calculatePieceCID-start')
- const pieceCid = calculatePieceCID(uint8Data)
- performance.mark('synapse:calculatePieceCID-end')
- performance.measure('synapse:calculatePieceCID', 'synapse:calculatePieceCID-start', 'synapse:calculatePieceCID-end')
- const size = uint8Data.length
-
- const requestBody = {
- pieceCid: pieceCid.toString(),
- // No notify URL needed
- }
-
- // Create upload session or check if piece exists
- performance.mark('synapse:POST.pdp.piece-start')
- const createResponse = await fetch(`${this._serviceURL}/pdp/piece`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(requestBody),
+ return await SP.uploadPiece({
+ endpoint: this._serviceURL,
+ data: uint8Data,
})
- performance.mark('synapse:POST.pdp.piece-end')
- performance.measure('synapse:POST.pdp.piece', 'synapse:POST.pdp.piece-start', 'synapse:POST.pdp.piece-end')
-
- if (createResponse.status === 200) {
- // Piece already exists on server
- return {
- pieceCid,
- size,
- }
- }
-
- if (createResponse.status !== 201) {
- const errorText = await createResponse.text()
- throw new Error(
- `Failed to create upload session: ${createResponse.status} ${createResponse.statusText} - ${errorText}`
- )
- }
-
- // Extract upload ID from Location header
- const location = createResponse.headers.get('Location')
- if (location == null) {
- throw new Error('Server did not provide Location header in response (may be restricted by CORS policy)')
- }
-
- // Validate the location format and extract UUID
- // Match /pdp/piece/upload/UUID or /piece/upload/UUID anywhere in the path
- const locationMatch = location.match(/\/(?:pdp\/)?piece\/upload\/([a-fA-F0-9-]+)/)
- if (locationMatch == null) {
- throw new Error(`Invalid Location header format: ${location}`)
- }
-
- const uploadUuid = locationMatch[1] // Extract just the UUID
-
- // Upload the data
- performance.mark('synapse:PUT.pdp.piece.upload-start')
- const uploadResponse = await fetch(`${this._serviceURL}/pdp/piece/upload/${uploadUuid}`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/octet-stream',
- 'Content-Length': uint8Data.length.toString(),
- // No Authorization header needed
- },
- body: uint8Data,
- })
- performance.mark('synapse:PUT.pdp.piece.upload-end')
- performance.measure(
- 'synapse:PUT.pdp.piece.upload',
- 'synapse:PUT.pdp.piece.upload-start',
- 'synapse:PUT.pdp.piece.upload-end'
- )
-
- if (uploadResponse.status !== 204) {
- const errorText = await uploadResponse.text()
- throw new Error(`Failed to upload piece: ${uploadResponse.status} ${uploadResponse.statusText} - ${errorText}`)
- }
-
- return {
- pieceCid,
- size,
- }
}
/**
@@ -611,29 +571,24 @@ export class PDPServer {
* @returns Promise that resolves with data set data
*/
async getDataSet(dataSetId: number): Promise {
- const response = await fetch(`${this._serviceURL}/pdp/data-sets/${dataSetId}`, {
- method: 'GET',
- headers: {
- Accept: 'application/json',
- },
+ const data = await SP.getDataSet({
+ endpoint: this._serviceURL,
+ dataSetId: BigInt(dataSetId),
})
- if (response.status === 404) {
- throw new Error(`Data set not found: ${dataSetId}`)
- }
-
- if (!response.ok) {
- const errorText = await response.text()
- throw new Error(`Failed to fetch data set: ${response.status} ${response.statusText} - ${errorText}`)
- }
-
- const data = await response.json()
- const converted = asDataSetData(data)
- if (converted == null) {
- console.error('Invalid data set data response:', data)
- throw new Error('Invalid data set data response format')
+ return {
+ id: data.id,
+ pieces: data.pieces.map((piece) => {
+ const pieceCid = Piece.parse(piece.pieceCid)
+ return {
+ pieceId: piece.pieceId,
+ pieceCid: pieceCid,
+ subPieceCid: pieceCid,
+ subPieceOffset: piece.subPieceOffset,
+ }
+ }),
+ nextChallengeEpoch: data.nextChallengeEpoch,
}
- return converted
}
/**
@@ -643,46 +598,45 @@ export class PDPServer {
* @param pieceID - The ID of the piece to delete
* @returns Promise for transaction hash of the delete operation
*/
- async deletePiece(dataSetId: number, clientDataSetId: number, pieceID: number): Promise {
- const authData = await this.getAuthHelper().signSchedulePieceRemovals(clientDataSetId, [pieceID])
- const payload = {
- extraData: `0x${authData.signature}`,
- }
-
- const response = await fetch(`${this._serviceURL}/pdp/data-sets/${dataSetId}/pieces/${pieceID}`, {
- method: 'DELETE',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(payload),
+ async deletePiece(dataSetId: number, clientDataSetId: bigint, pieceID: number): Promise {
+ const authData = await this.getAuthHelper().signSchedulePieceRemovals(clientDataSetId, [BigInt(pieceID)])
+
+ const { txHash } = await SP.deletePiece({
+ endpoint: this._serviceURL,
+ dataSetId: BigInt(dataSetId),
+ pieceId: BigInt(pieceID),
+ extraData: ethers.AbiCoder.defaultAbiCoder().encode(['bytes'], [authData.signature]) as Hex,
})
-
- if (response.status !== 200) {
- const errorText = await response.text()
- throw new Error(`Failed to delete piece: ${response.status} ${response.statusText} - ${errorText}`)
- }
- const data = await response.json()
- return validatePieceDeleteResponse(data).txHash
+ return txHash
}
/**
* Encode DataSetCreateData for extraData field
* This matches the Solidity struct DataSetCreateData in Warm Storage contract
*/
- private _encodeDataSetCreateData(data: { payer: string; metadata: MetadataEntry[]; signature: string }): string {
+ private _encodeDataSetCreateData(data: {
+ payer: string
+ clientDataSetId: bigint
+ metadata: MetadataEntry[]
+ signature: string
+ }): string {
// Ensure signature has 0x prefix
const signature = data.signature.startsWith('0x') ? data.signature : `0x${data.signature}`
// ABI encode the struct as a tuple
// DataSetCreateData struct:
// - address payer
+ // - uint256 clientDataSetId
// - string[] metadataKeys
// - string[] metadataValues
// - bytes signature
const keys = data.metadata.map((item) => item.key)
const values = data.metadata.map((item) => item.value)
const abiCoder = ethers.AbiCoder.defaultAbiCoder()
- const encoded = abiCoder.encode(['address', 'string[]', 'string[]', 'bytes'], [data.payer, keys, values, signature])
+ const encoded = abiCoder.encode(
+ ['address', 'uint256', 'string[]', 'string[]', 'bytes'],
+ [data.payer, data.clientDataSetId, keys, values, signature]
+ )
// Return hex string without 0x prefix (since we add it in the calling code)
return encoded.slice(2)
diff --git a/packages/synapse-sdk/src/pdp/validation.ts b/packages/synapse-sdk/src/pdp/validation.ts
index b9356f58..7de7ba0e 100644
--- a/packages/synapse-sdk/src/pdp/validation.ts
+++ b/packages/synapse-sdk/src/pdp/validation.ts
@@ -201,7 +201,6 @@ export function validateFindPieceResponse(value: unknown): FindPieceResponse {
// Return normalized response with PieceCID object
return {
pieceCid,
- piece_cid: obj.piece_cid, // Keep legacy field if it exists
}
}
diff --git a/packages/synapse-sdk/src/session/key.ts b/packages/synapse-sdk/src/session/key.ts
index 06f56484..22efcb27 100644
--- a/packages/synapse-sdk/src/session/key.ts
+++ b/packages/synapse-sdk/src/session/key.ts
@@ -13,7 +13,7 @@
* const expiries = await sessionKey.fetchExpiries([ADD_PIECES_TYPEHASH])
* if (expiries[ADD_PIECES_TYPEHASH] * BigInt(1000) < BigInt(Date.now()) + HOUR_MILLIS) {
* const DAY_MILLIS = BigInt(24) * HOUR_MILLIS
- * const loginTx = await sessionKey.login(BigInt(Date.now()) / BigInt(1000 + 30 * DAY_MILLIS), PDP_PERMISSIONS)
+ * const loginTx = await sessionKey.login(BigInt(Date.now()) / BigInt(1000 + 30 * DAY_MILLIS), PDP_PERMISSIONS, "example.com")
* const loginReceipt = await loginTx.wait()
* }
* synapse.setSession(sessionKey)
@@ -46,6 +46,8 @@ export const PDP_PERMISSION_NAMES: Record = {
[DELETE_DATA_SET_TYPEHASH]: 'DeleteDataSet',
}
+const DEFAULT_ORIGIN: string = (globalThis as any).location?.hostname || 'unknown'
+
export class SessionKey {
private readonly _provider: ethers.Provider
private readonly _registry: ethers.Contract
@@ -122,10 +124,15 @@ export class SessionKey {
*
* @param expiry unix time (block.timestamp) that the permissions expire
* @param permissions list of permissions granted to the signer, as a list of bytes32 hex strings
+ * @param origin the name of the application prompting this login
* @return signed and broadcasted login transaction details
*/
- async login(expiry: bigint, permissions: string[] = PDP_PERMISSIONS): Promise {
- return await this._registry.login(await this._signer.getAddress(), expiry, permissions)
+ async login(
+ expiry: bigint,
+ permissions: string[] = PDP_PERMISSIONS,
+ origin = DEFAULT_ORIGIN
+ ): Promise {
+ return await this._registry.login(await this._signer.getAddress(), expiry, permissions, origin)
}
/**
diff --git a/packages/synapse-sdk/src/sp-registry/service.ts b/packages/synapse-sdk/src/sp-registry/service.ts
index fe30144b..3854e6ae 100644
--- a/packages/synapse-sdk/src/sp-registry/service.ts
+++ b/packages/synapse-sdk/src/sp-registry/service.ts
@@ -179,14 +179,14 @@ export class SPRegistryService {
const contract = this._getRegistryContract()
const rawProvider = await contract.getProvider(providerId)
- if (rawProvider.serviceProvider === ethers.ZeroAddress) {
+ if (rawProvider.info.serviceProvider === ethers.ZeroAddress) {
return null
}
// Get products for this provider
const products = await this._getProviderProducts(providerId)
- return this._convertToProviderInfo(providerId, rawProvider, products)
+ return this._convertToProviderInfo(providerId, rawProvider.info, products)
} catch (error) {
if (error instanceof Error && error.message.includes('Provider not found')) {
return null
@@ -211,7 +211,7 @@ export class SPRegistryService {
])
// Check if provider exists (beneficiary address will be zero if not found)
- if (rawProvider.serviceProvider === ethers.ZeroAddress) {
+ if (rawProvider.info.serviceProvider === ethers.ZeroAddress) {
return null
}
@@ -219,7 +219,7 @@ export class SPRegistryService {
const products = await this._getProviderProducts(Number(providerId))
// Convert to ProviderInfo
- return this._convertToProviderInfo(Number(providerId), rawProvider, products)
+ return this._convertToProviderInfo(Number(providerId), rawProvider.info, products)
} catch {
return null
}
@@ -569,7 +569,7 @@ export class SPRegistryService {
const products = this._extractProductsFromMulticallResult(results[pdpServiceResultIndex], iface)
// Convert to ProviderInfo
- const providerInfo = this._convertToProviderInfo(providerIds[i], rawProvider, products)
+ const providerInfo = this._convertToProviderInfo(providerIds[i], rawProvider.info, products)
providers.push(providerInfo)
} catch {
// Skip failed decoding
@@ -695,7 +695,7 @@ export class SPRegistryService {
/**
* Convert raw provider data to ProviderInfo
*/
- private _convertToProviderInfo(providerId: number, rawProvider: any, productsArray: ServiceProduct[]): ProviderInfo {
+ private _convertToProviderInfo(providerId: number, providerInfo: any, productsArray: ServiceProduct[]): ProviderInfo {
// Convert products array to Record for direct access by type
const products: Partial> = {}
@@ -707,11 +707,11 @@ export class SPRegistryService {
return {
id: providerId,
- serviceProvider: rawProvider.serviceProvider,
- payee: rawProvider.payee,
- name: rawProvider.name,
- description: rawProvider.description,
- active: rawProvider.isActive,
+ serviceProvider: providerInfo.serviceProvider,
+ payee: providerInfo.payee,
+ name: providerInfo.name,
+ description: providerInfo.description,
+ active: providerInfo.isActive,
products,
}
}
diff --git a/packages/synapse-sdk/src/storage/context.ts b/packages/synapse-sdk/src/storage/context.ts
index 15f52945..ae24ebb5 100644
--- a/packages/synapse-sdk/src/storage/context.ts
+++ b/packages/synapse-sdk/src/storage/context.ts
@@ -55,6 +55,7 @@ import {
} from '../utils/index.ts'
import { combineMetadata, metadataMatches, objectToEntries, validatePieceMetadata } from '../utils/metadata.ts'
import { ProviderResolver } from '../utils/provider-resolver.ts'
+import { randIndex, randU256 } from '../utils/rand.ts'
import type { WarmStorageService } from '../warm-storage/index.ts'
export class StorageContext {
@@ -258,7 +259,7 @@ export class StorageContext {
// Create a new data set
// Get next client dataset ID
- const nextDatasetId = await warmStorageService.getNextClientDataSetId(clientAddress)
+ const nextDatasetId = randU256()
// Create auth helper for signing
const warmStorageAddress = synapse.getWarmStorageAddress()
@@ -488,7 +489,7 @@ export class StorageContext {
requestedMetadata,
warmStorageService,
providerResolver,
- client,
+ options.excludeProviderIds,
options.forceCreateDataSet,
options.withIpni,
options.dev
@@ -705,7 +706,7 @@ export class StorageContext {
requestedMetadata: Record,
warmStorageService: WarmStorageService,
providerResolver: ProviderResolver,
- signer: ethers.Signer,
+ excludeProviderIds?: number[],
forceCreateDataSet?: boolean,
withIpni?: boolean,
dev?: boolean
@@ -732,7 +733,7 @@ export class StorageContext {
// Create async generator that yields providers lazily
async function* generateProviders(): AsyncGenerator {
- const yieldedProviders = new Set()
+ const skipProviderIds = new Set(excludeProviderIds)
// First, yield providers from existing data sets (in sorted order)
for (const dataSet of sorted) {
@@ -744,8 +745,8 @@ export class StorageContext {
)
continue
}
- if (!yieldedProviders.has(provider.serviceProvider.toLowerCase())) {
- yieldedProviders.add(provider.serviceProvider.toLowerCase())
+ if (!skipProviderIds.has(provider.id)) {
+ skipProviderIds.add(provider.id)
yield provider
}
}
@@ -785,14 +786,16 @@ export class StorageContext {
}
// No existing data sets - select from all approved providers
- const allProviders = await providerResolver.getApprovedProviders()
+ const allProviders = (await providerResolver.getApprovedProviders()).filter(
+ (provider: ProviderInfo) => excludeProviderIds?.includes(provider.id) !== true
+ )
if (allProviders.length === 0) {
throw createError('StorageContext', 'smartSelectProvider', 'No approved service providers available')
}
// Random selection from all providers
- const provider = await StorageContext.selectRandomProvider(allProviders, signer, withIpni, dev)
+ const provider = await StorageContext.selectRandomProvider(allProviders, withIpni, dev)
return {
provider,
@@ -805,12 +808,12 @@ export class StorageContext {
/**
* Select a random provider from a list with ping validation
* @param providers - Array of providers to select from
- * @param signer - Signer for additional entropy
+ * @param withIpni - Filter for IPNI support
+ * @param dev - Include dev providers
* @returns Selected provider
*/
private static async selectRandomProvider(
providers: ProviderInfo[],
- signer?: ethers.Signer,
withIpni?: boolean,
dev?: boolean
): Promise {
@@ -823,34 +826,8 @@ export class StorageContext {
const remaining = [...providers]
while (remaining.length > 0) {
- let randomIndex: number
-
- // Try crypto.getRandomValues if available (HTTPS contexts)
- if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.getRandomValues != null) {
- const randomBytes = new Uint8Array(1)
- globalThis.crypto.getRandomValues(randomBytes)
- randomIndex = randomBytes[0] % remaining.length
- } else {
- // Fallback for HTTP contexts - use multiple entropy sources
- const timestamp = Date.now()
- const random = Math.random()
-
- if (signer != null) {
- // Use wallet address as additional entropy
- const addressBytes = await signer.getAddress()
- const addressSum = addressBytes.split('').reduce((a, c) => a + c.charCodeAt(0), 0)
-
- // Combine sources for better distribution
- const combined = (timestamp * random * addressSum) % remaining.length
- randomIndex = Math.floor(Math.abs(combined))
- } else {
- // No signer available, use simpler fallback
- randomIndex = Math.floor(Math.random() * remaining.length)
- }
- }
-
// Remove and yield the selected provider
- const selected = remaining.splice(randomIndex, 1)[0]
+ const selected = remaining.splice(randIndex(remaining.length), 1)[0]
yield selected
}
}
@@ -1014,31 +991,11 @@ export class StorageContext {
}
// Poll for piece to be "parked" (ready)
- const maxWaitTime = TIMING_CONSTANTS.PIECE_PARKING_TIMEOUT_MS
- const pollInterval = TIMING_CONSTANTS.PIECE_PARKING_POLL_INTERVAL_MS
- const startTime = Date.now()
- let pieceReady = false
-
performance.mark('synapse:findPiece-start')
- while (Date.now() - startTime < maxWaitTime) {
- try {
- await this._pdpServer.findPiece(uploadResult.pieceCid)
- pieceReady = true
- break
- } catch {
- // Piece not ready yet, wait and retry if we haven't exceeded timeout
- if (Date.now() - startTime + pollInterval < maxWaitTime) {
- await new Promise((resolve) => setTimeout(resolve, pollInterval))
- }
- }
- }
+ await this._pdpServer.findPiece(uploadResult.pieceCid)
performance.mark('synapse:findPiece-end')
performance.measure('synapse:findPiece', 'synapse:findPiece-start', 'synapse:findPiece-end')
- if (!pieceReady) {
- throw createError('StorageContext', 'findPiece', 'Timeout waiting for piece to be parked on service provider')
- }
-
// Upload phase complete - remove from active tracking
this._activeUploads.delete(uploadId)
diff --git a/packages/synapse-sdk/src/storage/manager.ts b/packages/synapse-sdk/src/storage/manager.ts
index d64d3ba0..bb4f8264 100644
--- a/packages/synapse-sdk/src/storage/manager.ts
+++ b/packages/synapse-sdk/src/storage/manager.ts
@@ -252,7 +252,10 @@ export class StorageManager {
if (canUseDefault) {
// Check if we have a default context with compatible metadata
- if (this._defaultContext != null) {
+ if (
+ this._defaultContext != null &&
+ options?.excludeProviderIds?.includes(this._defaultContext.provider.id) !== true
+ ) {
// Combine the current request metadata with effective withCDN setting
const requestedMetadata = combineMetadata(options?.metadata, effectiveWithCDN)
diff --git a/packages/synapse-sdk/src/synapse.ts b/packages/synapse-sdk/src/synapse.ts
index 11b30213..27c73ae4 100644
--- a/packages/synapse-sdk/src/synapse.ts
+++ b/packages/synapse-sdk/src/synapse.ts
@@ -267,7 +267,7 @@ export class Synapse {
* const HOUR_MILLIS = BigInt(1000 * 60 * 60)
* if (expiries[ADD_PIECES_TYPEHASH] * BigInt(1000) < BigInt(Date.now()) + HOUR_MILLIS) {
* const DAY_MILLIS = BigInt(24) * HOUR_MILLIS
- * const loginTx = await sessionKey.login(BigInt(Date.now()) / BigInt(1000 + 30 * DAY_MILLIS), PDP_PERMISSIONS)
+ * const loginTx = await sessionKey.login(BigInt(Date.now()) / BigInt(1000 + 30 * DAY_MILLIS), PDP_PERMISSIONS, "example.com")
* const loginReceipt = await loginTx.wait()
* }
*
diff --git a/packages/synapse-sdk/src/test/metadata-selection.test.ts b/packages/synapse-sdk/src/test/metadata-selection.test.ts
index 32ee304d..e1ebdc4c 100644
--- a/packages/synapse-sdk/src/test/metadata-selection.test.ts
+++ b/packages/synapse-sdk/src/test/metadata-selection.test.ts
@@ -148,6 +148,7 @@ describe('Metadata-based Data Set Selection', () => {
pdpEndEpoch: 0n,
providerId: 1n,
cdnEndEpoch: 0n,
+ dataSetId,
},
]
}
@@ -165,6 +166,7 @@ describe('Metadata-based Data Set Selection', () => {
pdpEndEpoch: 0n,
providerId: 1n,
cdnEndEpoch: 0n,
+ dataSetId,
},
]
}
@@ -182,6 +184,7 @@ describe('Metadata-based Data Set Selection', () => {
pdpEndEpoch: 0n,
providerId: 2n,
cdnEndEpoch: 0n,
+ dataSetId,
},
]
}
@@ -199,6 +202,7 @@ describe('Metadata-based Data Set Selection', () => {
pdpEndEpoch: 0n,
providerId: 0n,
cdnEndEpoch: 0n,
+ dataSetId,
},
]
},
diff --git a/packages/synapse-sdk/src/test/metadata.test.ts b/packages/synapse-sdk/src/test/metadata.test.ts
index eba2a39f..ec230014 100644
--- a/packages/synapse-sdk/src/test/metadata.test.ts
+++ b/packages/synapse-sdk/src/test/metadata.test.ts
@@ -64,7 +64,7 @@ describe('Metadata Support', () => {
)
const result = await pdpServer.createDataSet(
- 1,
+ 1n,
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payer
dataSetMetadata,
@@ -103,7 +103,7 @@ describe('Metadata Support', () => {
)
// Test with matching metadata
- const result = await pdpServer.addPieces(dataSetId, 1, 1, pieces, metadata)
+ const result = await pdpServer.addPieces(dataSetId, 1n, 1, pieces, metadata)
assert.equal(result.txHash, mockTxHash)
assert.exists(capturedPieceMetadata)
assert.isNotNull(capturedPieceMetadata)
@@ -117,7 +117,7 @@ describe('Metadata Support', () => {
]
try {
- await pdpServer.addPieces(dataSetId, 1, 1, pieces, mismatchedMetadata)
+ await pdpServer.addPieces(dataSetId, 1n, 1, pieces, mismatchedMetadata)
assert.fail('Should have thrown an error')
} catch (error: any) {
assert.match(error.message, /Metadata length \(2\) must match pieces length \(1\)/)
@@ -125,7 +125,7 @@ describe('Metadata Support', () => {
// Test without metadata (should create empty arrays)
capturedPieceMetadata = null
- const resultNoMetadata = await pdpServer.addPieces(dataSetId, 1, 1, pieces)
+ const resultNoMetadata = await pdpServer.addPieces(dataSetId, 1n, 1, pieces)
assert.equal(resultNoMetadata.txHash, mockTxHash)
assert.exists(capturedPieceMetadata)
assert.isNotNull(capturedPieceMetadata)
@@ -156,7 +156,7 @@ describe('Metadata Support', () => {
]
await pdpServer.createDataSet(
- 1,
+ 1n,
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payer
metadataWithCDN,
@@ -171,7 +171,7 @@ describe('Metadata Support', () => {
const metadataWithoutCDN: MetadataEntry[] = [{ key: 'project', value: 'test' }]
await pdpServer.createDataSet(
- 1,
+ 1n,
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payer
metadataWithoutCDN,
diff --git a/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts b/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts
index 7ddc057f..9ca11533 100644
--- a/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts
+++ b/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts
@@ -245,7 +245,7 @@ export const presets = {
pdpVerifierAddress: () => [ADDRESSES.calibration.pdpVerifier],
paymentsContractAddress: () => [ADDRESSES.calibration.payments],
usdfcTokenAddress: () => [ADDRESSES.calibration.usdfcToken],
- filCDNBeneficiaryAddress: () => [ADDRESSES.calibration.filCDN],
+ filBeamBeneficiaryAddress: () => [ADDRESSES.calibration.filCDN],
viewContractAddress: () => [ADDRESSES.calibration.viewContract],
serviceProviderRegistry: () => [ADDRESSES.calibration.spRegistry],
sessionKeyRegistry: () => [ADDRESSES.calibration.sessionKeyRegistry],
@@ -275,6 +275,7 @@ export const presets = {
pdpEndEpoch: 0n,
providerId: 1n,
cdnEndEpoch: 0n,
+ dataSetId: 1n,
},
],
],
@@ -293,6 +294,7 @@ export const presets = {
pdpEndEpoch: 0n,
providerId: 1n,
cdnEndEpoch: 0n,
+ dataSetId: 1n,
},
],
getApprovedProviders: () => [[1n, 2n]],
@@ -329,7 +331,7 @@ export const presets = {
return [true, 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi']
return [false, ''] // key not found
},
- clientDataSetIDs: () => {
+ clientDataSetIds: () => {
return [BigInt(0)]
},
},
@@ -341,12 +343,14 @@ export const presets = {
serviceRegistry: {
getProviderByAddress: (data) => [
{
- serviceProvider: data[0],
- payee: ADDRESSES.payee1,
- isActive: true,
- name: 'Test Provider',
- description: 'Test Provider',
providerId: 1n,
+ info: {
+ serviceProvider: data[0],
+ payee: ADDRESSES.payee1,
+ isActive: true,
+ name: 'Test Provider',
+ description: 'Test Provider',
+ },
},
],
getProviderIdByAddress: () => [1n],
@@ -369,35 +373,41 @@ export const presets = {
if (data[0] === 1n) {
return [
{
- serviceProvider: ADDRESSES.serviceProvider1,
- payee: ADDRESSES.payee1,
- isActive: true,
- name: 'Test Provider',
- description: 'Test Provider',
providerId: 1n,
+ info: {
+ serviceProvider: ADDRESSES.serviceProvider1,
+ payee: ADDRESSES.payee1,
+ isActive: true,
+ name: 'Test Provider',
+ description: 'Test Provider',
+ },
},
]
}
if (data[0] === 2n) {
return [
{
- serviceProvider: ADDRESSES.serviceProvider2,
- payee: ADDRESSES.payee1,
- isActive: true,
- name: 'Test Provider',
- description: 'Test Provider',
providerId: 2n,
+ info: {
+ serviceProvider: ADDRESSES.serviceProvider2,
+ payee: ADDRESSES.payee1,
+ isActive: true,
+ name: 'Test Provider',
+ description: 'Test Provider',
+ },
},
]
}
return [
{
- serviceProvider: ADDRESSES.zero,
- payee: ADDRESSES.zero,
- isActive: false,
- name: '',
- description: '',
providerId: 0n,
+ info: {
+ serviceProvider: ADDRESSES.zero,
+ payee: ADDRESSES.zero,
+ isActive: false,
+ name: '',
+ description: '',
+ },
},
]
},
diff --git a/packages/synapse-sdk/src/test/mocks/jsonrpc/warm-storage.ts b/packages/synapse-sdk/src/test/mocks/jsonrpc/warm-storage.ts
index 4cf8b0ac..dc59e95f 100644
--- a/packages/synapse-sdk/src/test/mocks/jsonrpc/warm-storage.ts
+++ b/packages/synapse-sdk/src/test/mocks/jsonrpc/warm-storage.ts
@@ -28,7 +28,7 @@ export type getAllPieceMetadata = ExtractAbiFunction
-export type clientDataSetIDs = ExtractAbiFunction
+export type clientDataSetIds = ExtractAbiFunction
export interface WarmStorageViewOptions {
isProviderApproved?: (args: AbiToType) => AbiToType
@@ -43,7 +43,7 @@ export interface WarmStorageViewOptions {
getDataSetMetadata?: (args: AbiToType) => AbiToType
getAllPieceMetadata?: (args: AbiToType) => AbiToType
getPieceMetadata?: (args: AbiToType) => AbiToType
- clientDataSetIDs?: (args: AbiToType) => AbiToType
+ clientDataSetIds?: (args: AbiToType) => AbiToType
}
/**
@@ -56,7 +56,10 @@ export type paymentsContractAddress = ExtractAbiFunction
-export type filCDNBeneficiaryAddress = ExtractAbiFunction
+export type filBeamBeneficiaryAddress = ExtractAbiFunction<
+ typeof CONTRACT_ABIS.WARM_STORAGE,
+ 'filBeamBeneficiaryAddress'
+>
export type viewContractAddress = ExtractAbiFunction
@@ -72,9 +75,9 @@ export interface WarmStorageOptions {
args: AbiToType
) => AbiToType
usdfcTokenAddress?: (args: AbiToType) => AbiToType
- filCDNBeneficiaryAddress?: (
- args: AbiToType
- ) => AbiToType
+ filBeamBeneficiaryAddress?: (
+ args: AbiToType
+ ) => AbiToType
viewContractAddress?: (args: AbiToType) => AbiToType
serviceProviderRegistry?: (
args: AbiToType
@@ -123,13 +126,13 @@ export function warmStorageCallHandler(data: Hex, options: JSONRPCOptions): Hex
options.warmStorage.usdfcTokenAddress(args)
)
}
- case 'filCDNBeneficiaryAddress': {
- if (!options.warmStorage?.filCDNBeneficiaryAddress) {
- throw new Error('Warm Storage: filCDNBeneficiaryAddress is not defined')
+ case 'filBeamBeneficiaryAddress': {
+ if (!options.warmStorage?.filBeamBeneficiaryAddress) {
+ throw new Error('Warm Storage: filBeamBeneficiaryAddress is not defined')
}
return encodeAbiParameters(
[{ name: '', internalType: 'address', type: 'address' }],
- options.warmStorage.filCDNBeneficiaryAddress(args)
+ options.warmStorage.filBeamBeneficiaryAddress(args)
)
}
case 'viewContractAddress': {
@@ -293,14 +296,14 @@ export function warmStorageViewCallHandler(data: Hex, options: JSONRPCOptions):
options.warmStorageView.getPieceMetadata(args)
)
}
- case 'clientDataSetIDs': {
- if (!options.warmStorageView?.clientDataSetIDs) {
- throw new Error('Warm Storage View: clientDataSetIDs is not defined')
+ case 'clientDataSetIds': {
+ if (!options.warmStorageView?.clientDataSetIds) {
+ throw new Error('Warm Storage View: clientDataSetIds is not defined')
}
return encodeAbiParameters(
- CONTRACT_ABIS.WARM_STORAGE_VIEW.find((abi) => abi.type === 'function' && abi.name === 'clientDataSetIDs')!
+ CONTRACT_ABIS.WARM_STORAGE_VIEW.find((abi) => abi.type === 'function' && abi.name === 'clientDataSetIds')!
.outputs,
- options.warmStorageView.clientDataSetIDs(args)
+ options.warmStorageView.clientDataSetIds(args)
)
}
diff --git a/packages/synapse-sdk/src/test/mocks/pdp/handlers.ts b/packages/synapse-sdk/src/test/mocks/pdp/handlers.ts
index 797e4106..41f22353 100644
--- a/packages/synapse-sdk/src/test/mocks/pdp/handlers.ts
+++ b/packages/synapse-sdk/src/test/mocks/pdp/handlers.ts
@@ -181,12 +181,12 @@ export function findPieceHandler(pieceCid: string, found: boolean, options: PDPM
/**
* Helper to decode metadata from extraData
*/
-export function decodeMetadataFromExtraData(extraData: string): MetadataCapture {
+export function decodeMetadataFromCreateDataSetExtraData(extraData: string): MetadataCapture {
const abiCoder = ethers.AbiCoder.defaultAbiCoder()
- const decoded = abiCoder.decode(['address', 'string[]', 'string[]', 'bytes'], extraData)
+ const decoded = abiCoder.decode(['address', 'uint256', 'string[]', 'string[]', 'bytes'], extraData)
return {
- keys: decoded[1] as string[],
- values: decoded[2] as string[],
+ keys: decoded[2] as string[],
+ values: decoded[3] as string[],
}
}
@@ -223,7 +223,7 @@ export function createDataSetWithMetadataCapture(
}
try {
- const metadata = decodeMetadataFromExtraData(body.extraData)
+ const metadata = decodeMetadataFromCreateDataSetExtraData(body.extraData)
captureCallback(metadata)
if (options.debug) {
diff --git a/packages/synapse-sdk/src/test/pdp-auth.test.ts b/packages/synapse-sdk/src/test/pdp-auth.test.ts
index 3c17d39c..9f678745 100644
--- a/packages/synapse-sdk/src/test/pdp-auth.test.ts
+++ b/packages/synapse-sdk/src/test/pdp-auth.test.ts
@@ -36,7 +36,7 @@ const FIXTURES = {
signature:
'0xc77965e2b6efd594629c44eb61127bc3133b65d08c25f8aa33e3021e7f46435845ab67ffbac96afc4b4671ecbd32d4869ca7fe1c0eaa5affa942d0abbfd98d601b',
digest: '0xd89be6a725302e66575d7a9c730191a84e2a624d0f0f3976194d0bd6f2927640',
- clientDataSetId: 12345,
+ clientDataSetId: 12345n,
payee: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
metadata: [{ key: 'title', value: 'TestDataSet' }],
},
@@ -44,8 +44,8 @@ const FIXTURES = {
signature:
'0x215d2d6ea06c7daad46e3e636b305885c7d09aa34420e8dbace032af03cae06224cf678da808c7f1026b08ccf51f3d5d53351b935f5eee9750b80e78caffaaa91c',
digest: '0xa690b5f3c6400833822aa3fd63ad1f0e4c1f70e5cc132cfd898c2993169d23bf',
- clientDataSetId: 12345,
- firstAdded: 1,
+ clientDataSetId: 12345n,
+ firstAdded: 1n,
pieceCidBytes: [
'0x01559120220500de6815dcb348843215a94de532954b60be550a4bec6e74555665e9a5ec4e0f3c',
'0x01559120227e03642a607ef886b004bf2c1978463ae1d4693ac0f410eb2d1b7a47fe205e5e750f',
@@ -56,14 +56,14 @@ const FIXTURES = {
signature:
'0xcb8e645f2894fde89de54d4a54eb1e0d9871901c6fa1c2ee8a0390dc3a29e6cb2244d0561e3eca6452fa59efaab3d4b18a0b5b59ab52e233b3469422556ae9c61c',
digest: '0xef55929f8dd724ef4b43c5759db26878608f7e1277d168e3e621d3cd4ba682dd',
- clientDataSetId: 12345,
- pieceIds: [1, 3, 5],
+ clientDataSetId: 12345n,
+ pieceIds: [1n, 3n, 5n],
},
deleteDataSet: {
signature:
'0x94e366bd2f9bfc933a87575126715bccf128b77d9c6937e194023e13b54272eb7a74b7e6e26acf4341d9c56e141ff7ba154c37ea03e9c35b126fff1efe1a0c831c',
digest: '0x79df79ba922d913eccb0f9a91564ba3a1a81a0ea81d99a7cecf23cc3f425cafb',
- clientDataSetId: 12345,
+ clientDataSetId: 12345n,
},
},
}
diff --git a/packages/synapse-sdk/src/test/pdp-server.test.ts b/packages/synapse-sdk/src/test/pdp-server.test.ts
index 4c9b8eaa..4828c6d5 100644
--- a/packages/synapse-sdk/src/test/pdp-server.test.ts
+++ b/packages/synapse-sdk/src/test/pdp-server.test.ts
@@ -6,6 +6,16 @@
* Tests the PDPServer class for creating data sets and adding pieces via HTTP API
*/
+import {
+ AddPiecesError,
+ CreateDataSetError,
+ DeletePieceError,
+ FindPieceError,
+ GetDataSetError,
+ LocationHeaderError,
+ PostPieceError,
+} from '@filoz/synapse-core/errors'
+import * as SP from '@filoz/synapse-core/sp'
import { assert } from 'chai'
import { ethers } from 'ethers'
import { setup } from 'iso-web/msw'
@@ -83,7 +93,7 @@ describe('PDPServer', () => {
)
const result = await pdpServer.createDataSet(
- 0, // clientDataSetId
+ 0n, // clientDataSetId
'0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
await signer.getAddress(), // payer
[], // metadata (empty for no CDN)
@@ -93,6 +103,162 @@ describe('PDPServer', () => {
assert.strictEqual(result.txHash, mockTxHash)
assert.include(result.statusUrl, mockTxHash)
})
+
+ it('should fail for unexpected location header', async () => {
+ server.use(
+ http.post('http://pdp.local/pdp/data-sets', () => {
+ return new HttpResponse(null, {
+ status: 201,
+ headers: { Location: `/pdp/data-sets/created/invalid-hash` },
+ })
+ })
+ )
+ try {
+ await pdpServer.createDataSet(
+ 0n, // clientDataSetId
+ '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
+ await signer.getAddress(), // payer
+ [], // metadata (empty for no CDN)
+ TEST_CONTRACT_ADDRESS // recordKeeper
+ )
+ assert.fail('Should have thrown error for unexpected location header')
+ } catch (error) {
+ assert.instanceOf(error, LocationHeaderError)
+ assert.equal(error.message, 'Location header format is invalid: /pdp/data-sets/created/invalid-hash')
+ }
+ })
+ it('should fail with no Location header', async () => {
+ server.use(
+ http.post('http://pdp.local/pdp/data-sets', () => {
+ return new HttpResponse(null, {
+ status: 201,
+ headers: {},
+ })
+ })
+ )
+ try {
+ await pdpServer.createDataSet(
+ 0n, // clientDataSetId
+ '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
+ await signer.getAddress(), // payer
+ [], // metadata (empty for no CDN)
+ TEST_CONTRACT_ADDRESS // recordKeeper
+ )
+ assert.fail('Should have thrown error for no Location header')
+ } catch (error) {
+ assert.instanceOf(error, LocationHeaderError)
+ assert.equal(error.message, 'Location header format is invalid: ')
+ }
+ })
+
+ it('should fail with CreateDataSetError string error', async () => {
+ server.use(
+ http.post('http://pdp.local/pdp/data-sets', () => {
+ return HttpResponse.text(
+ `Failed to send transaction: failed to estimate gas: message execution failed (exit=[33], revert reason=[message failed with backtrace:
+00: f0169791 (method 3844450837) -- contract reverted at 75 (33)
+01: f0169791 (method 6) -- contract reverted at 4535 (33)
+02: f0169800 (method 3844450837) -- contract reverted at 75 (33)
+03: f0169800 (method 6) -- contract reverted at 10988 (33)
+04: f0169792 (method 3844450837) -- contract reverted at 1775 (33)
+ (RetCode=33)], vm error=[Error(invariant failure: insufficient funds to cover lockup after function execution)])
+`,
+ {
+ status: 500,
+ }
+ )
+ })
+ )
+ try {
+ await pdpServer.createDataSet(
+ 0n, // clientDataSetId
+ '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
+ await signer.getAddress(), // payer
+ [], // metadata (empty for no CDN)
+ TEST_CONTRACT_ADDRESS // recordKeeper
+ )
+ assert.fail('Should have thrown error for no Location header')
+ } catch (error) {
+ assert.instanceOf(error, CreateDataSetError)
+ assert.equal(error.shortMessage, 'Failed to create data set.')
+ assert.equal(
+ error.message,
+ `Failed to create data set.
+
+Details:
+invariant failure: insufficient funds to cover lockup after function execution`
+ )
+ }
+ })
+
+ it('should fail with CreateDataSetError typed error', async () => {
+ server.use(
+ http.post('http://pdp.local/pdp/data-sets', () => {
+ return HttpResponse.text(
+ `Failed to send transaction: failed to estimate gas: message execution failed (exit=[33], revert reason=[message failed with backtrace:
+00: f0169791 (method 3844450837) -- contract reverted at 75 (33)
+01: f0169791 (method 6) -- contract reverted at 4535 (33)
+02: f0169800 (method 3844450837) -- contract reverted at 75 (33)
+03: f0169800 (method 6) -- contract reverted at 18957 (33)
+ (RetCode=33)], vm error=[0x42d750dc0000000000000000000000007e4abd63a7c8314cc28d388303472353d884f292000000000000000000000000b0ff6622d99a325151642386f65ab33a08c30213])
+`,
+ {
+ status: 500,
+ }
+ )
+ })
+ )
+ try {
+ await pdpServer.createDataSet(
+ 0n, // clientDataSetId
+ '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', // payee
+ await signer.getAddress(), // payer
+ [], // metadata (empty for no CDN)
+ TEST_CONTRACT_ADDRESS // recordKeeper
+ )
+ assert.fail('Should have thrown error for no Location header')
+ } catch (error) {
+ assert.instanceOf(error, CreateDataSetError)
+ assert.equal(error.shortMessage, 'Failed to create data set.')
+ assert.equal(
+ error.message,
+ `Failed to create data set.
+
+Details: Warm Storage
+InvalidSignature(address expected, address actual)
+ (0x7e4ABd63A7C8314Cc28D388303472353D884f292, 0xb0fF6622D99A325151642386F65AB33a08c30213)`
+ )
+ }
+ })
+ })
+
+ describe('createAndAddPieces', () => {
+ it('should handle successful data set creation', async () => {
+ // Mock the createDataSet endpoint
+ const mockTxHash = '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
+ const validPieceCid = ['bafkzcibcd4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy']
+
+ server.use(
+ http.post('http://pdp.local/pdp/data-sets/create-and-add', () => {
+ return new HttpResponse(null, {
+ status: 201,
+ headers: { Location: `/pdp/data-sets/created/${mockTxHash}` },
+ })
+ })
+ )
+
+ const result = await pdpServer.createAndAddPieces(
+ 0n,
+ '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
+ await signer.getAddress(),
+ TEST_CONTRACT_ADDRESS,
+ validPieceCid,
+ {}
+ )
+
+ assert.strictEqual(result.txHash, mockTxHash)
+ assert.include(result.statusUrl, mockTxHash)
+ })
})
describe('getPieceAdditionStatus', () => {
@@ -193,7 +359,7 @@ describe('PDPServer', () => {
it('should validate input parameters', async () => {
// Test empty piece entries
try {
- await pdpServer.addPieces(1, 0, 0, [])
+ await pdpServer.addPieces(1, 0n, 0, [])
assert.fail('Should have thrown error for empty piece entries')
} catch (error) {
assert.include((error as Error).message, 'At least one piece must be provided')
@@ -203,7 +369,7 @@ describe('PDPServer', () => {
const invalidPieceCid = 'invalid-piece-link-string'
try {
- await pdpServer.addPieces(1, 0, 0, [invalidPieceCid])
+ await pdpServer.addPieces(1, 0n, 0, [invalidPieceCid])
assert.fail('Should have thrown error for invalid PieceCID')
} catch (error) {
assert.include((error as Error).message, 'Invalid PieceCID')
@@ -216,7 +382,7 @@ describe('PDPServer', () => {
server.use(
http.post<{ id: string }, PDPAddPiecesInput>(
'http://pdp.local/pdp/data-sets/:id/pieces',
- async ({ request }) => {
+ async ({ request, params }) => {
try {
const body = await request.json()
assert.isDefined(body.pieces)
@@ -227,6 +393,9 @@ describe('PDPServer', () => {
assert.strictEqual(body.pieces[0].subPieces[0].subPieceCid, validPieceCid[0]) // Piece is its own subPiece
return HttpResponse.text('Pieces added successfully', {
status: 201,
+ headers: {
+ Location: `/pdp/data-sets/${params.id}/pieces/added/0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef123456`,
+ },
})
} catch (error) {
return HttpResponse.text((error as Error).message, {
@@ -238,7 +407,7 @@ describe('PDPServer', () => {
)
// Should not throw
- const result = await pdpServer.addPieces(1, 0, 0, validPieceCid)
+ const result = await pdpServer.addPieces(1, 0n, 0, validPieceCid)
assert.isDefined(result)
assert.isDefined(result.message)
})
@@ -256,12 +425,17 @@ describe('PDPServer', () => {
)
try {
- await pdpServer.addPieces(1, 0, 0, validPieceCid)
+ await pdpServer.addPieces(1, 0n, 0, validPieceCid)
assert.fail('Should have thrown error for server error')
} catch (error) {
- assert.include(
- (error as Error).message,
- 'Failed to add pieces to data set: 400 Bad Request - Invalid piece CID'
+ assert.instanceOf(error, AddPiecesError)
+ assert.equal(error.shortMessage, 'Failed to add pieces.')
+ assert.equal(
+ error.message,
+ `Failed to add pieces.
+
+Details: Service Provider PDP
+Invalid piece CID`
)
}
})
@@ -282,7 +456,7 @@ describe('PDPServer', () => {
server.use(
http.post<{ id: string }, PDPAddPiecesInput>(
'http://pdp.local/pdp/data-sets/:id/pieces',
- async ({ request }) => {
+ async ({ request, params }) => {
try {
const body = await request.json()
assert.strictEqual(body.pieces.length, 2)
@@ -293,6 +467,9 @@ describe('PDPServer', () => {
return HttpResponse.text('Multiple pieces added successfully', {
status: 201,
+ headers: {
+ Location: `/pdp/data-sets/${params.id}/pieces/added/0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef123456`,
+ },
})
} catch (error) {
return HttpResponse.text((error as Error).message, {
@@ -302,7 +479,7 @@ describe('PDPServer', () => {
}
)
)
- const result = await pdpServer.addPieces(1, 0, 0, multiplePieceCid)
+ const result = await pdpServer.addPieces(1, 0n, 0, multiplePieceCid)
assert.isDefined(result)
assert.isDefined(result.message)
})
@@ -322,55 +499,13 @@ describe('PDPServer', () => {
})
)
- const result = await pdpServer.addPieces(1, 0, 0, validPieceCid)
+ const result = await pdpServer.addPieces(1, 0n, 0, validPieceCid)
assert.isDefined(result)
assert.isDefined(result.message)
assert.strictEqual(result.txHash, mockTxHash)
assert.include(result.statusUrl ?? '', mockTxHash)
assert.include(result.statusUrl ?? '', '/pdp/data-sets/1/pieces/added/')
})
-
- it('should handle addPieces response with Location header missing 0x prefix', async () => {
- const validPieceCid = ['bafkzcibcd4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy']
- const mockTxHashWithout0x = 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'
- const mockTxHashWith0x = `0x${mockTxHashWithout0x}`
-
- server.use(
- http.post('http://pdp.local/pdp/data-sets/:id/pieces', async () => {
- return HttpResponse.text('Pieces added successfully', {
- status: 201,
- headers: {
- Location: `/pdp/data-sets/1/pieces/added/${mockTxHashWithout0x}`,
- },
- })
- })
- )
-
- const result = await pdpServer.addPieces(1, 0, 0, validPieceCid)
- assert.isDefined(result)
- assert.strictEqual(result.txHash, mockTxHashWith0x) // Should have 0x prefix added
- })
-
- it('should handle malformed Location header gracefully', async () => {
- const validPieceCid = ['bafkzcibcd4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy']
-
- server.use(
- http.post('http://pdp.local/pdp/data-sets/:id/pieces', async () => {
- return HttpResponse.text('Pieces added successfully', {
- status: 201,
- headers: {
- Location: '/some/unexpected/path',
- },
- })
- })
- )
-
- const result = await pdpServer.addPieces(1, 0, 0, validPieceCid)
- assert.isDefined(result)
- assert.isDefined(result.message)
- assert.isUndefined(result.txHash) // No txHash for malformed Location
- assert.isUndefined(result.statusUrl)
- })
})
describe('deletePiece', () => {
@@ -389,7 +524,7 @@ describe('PDPServer', () => {
})
})
)
- const result = await pdpServer.deletePiece(1, 0, 2)
+ const result = await pdpServer.deletePiece(1, 0n, 2)
assert.strictEqual(result, mockTxHash)
})
@@ -402,11 +537,18 @@ describe('PDPServer', () => {
})
)
try {
- await pdpServer.deletePiece(1, 0, 2)
+ await pdpServer.deletePiece(1, 0n, 2)
assert.fail('Should have thrown error for server error')
} catch (error: any) {
- assert.include(error.message, 'Failed to delete piece')
- assert.include(error.message, '500')
+ assert.instanceOf(error, DeletePieceError)
+ assert.equal(error.shortMessage, 'Failed to delete piece.')
+ assert.equal(
+ error.message,
+ `Failed to delete piece.
+
+Details: Service Provider PDP
+Database error`
+ )
}
})
})
@@ -475,6 +617,7 @@ describe('PDPServer', () => {
})
it('should handle piece not found', async () => {
+ SP.setTimeout(100)
const mockPieceCid = 'bafkzcibcd4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy'
server.use(
@@ -489,8 +632,15 @@ describe('PDPServer', () => {
await pdpServer.findPiece(mockPieceCid)
assert.fail('Should have thrown error for not found')
} catch (error: any) {
- assert.include(error.message, 'Piece not found')
- assert.include(error.message, mockPieceCid)
+ assert.instanceOf(error, FindPieceError)
+ assert.equal(error.shortMessage, 'Failed to find piece.')
+ assert.equal(
+ error.message,
+ `Failed to find piece.
+
+Details: Service Provider PDP
+Timeout waiting for piece to be found`
+ )
}
})
@@ -519,9 +669,15 @@ describe('PDPServer', () => {
await pdpServer.findPiece(mockPieceCid)
assert.fail('Should have thrown error for server error')
} catch (error: any) {
- assert.include(error.message, 'Failed to find piece')
- assert.include(error.message, '500')
- assert.include(error.message, 'Database error')
+ assert.instanceOf(error, FindPieceError)
+ assert.equal(error.shortMessage, 'Failed to find piece.')
+ assert.equal(
+ error.message,
+ `Failed to find piece.
+
+Details: Service Provider PDP
+Database error`
+ )
}
})
})
@@ -795,9 +951,15 @@ describe('PDPServer', () => {
await pdpServer.uploadPiece(testData)
assert.fail('Should have thrown error')
} catch (error: any) {
- assert.include(error.message, 'Failed to create upload session')
- assert.include(error.message, '500')
- assert.include(error.message, 'Database error')
+ assert.instanceOf(error, PostPieceError)
+ assert.equal(error.shortMessage, 'Failed to create upload session.')
+ assert.equal(
+ error.message,
+ `Failed to create upload session.
+
+Details: Service Provider PDP
+Database error`
+ )
}
})
})
@@ -1054,14 +1216,12 @@ describe('PDPServer', () => {
assert.equal(result.pieces.length, mockDataSetData.pieces.length)
assert.equal(result.pieces[0].pieceId, mockDataSetData.pieces[0].pieceId)
assert.equal(result.pieces[0].pieceCid.toString(), mockDataSetData.pieces[0].pieceCid)
- assert.equal(result.pieces[0].subPieceCid.toString(), mockDataSetData.pieces[0].subPieceCid)
- assert.equal(result.pieces[0].subPieceOffset, mockDataSetData.pieces[0].subPieceOffset)
})
it('should handle data set not found', async () => {
server.use(
http.get('http://pdp.local/pdp/data-sets/999', async () => {
- return HttpResponse.json(undefined, {
+ return new HttpResponse(null, {
status: 404,
})
})
@@ -1071,7 +1231,8 @@ describe('PDPServer', () => {
await pdpServer.getDataSet(999)
assert.fail('Should have thrown error for not found data set')
} catch (error) {
- assert.include((error as Error).message, 'Data set not found: 999')
+ assert.instanceOf(error, GetDataSetError)
+ assert.equal(error.shortMessage, 'Data set not found.')
}
})
@@ -1088,32 +1249,9 @@ describe('PDPServer', () => {
await pdpServer.getDataSet(292)
assert.fail('Should have thrown error for server error')
} catch (error) {
- assert.include((error as Error).message, 'Failed to fetch data set')
- assert.include((error as Error).message, '500')
- assert.include((error as Error).message, 'Database error')
- }
- })
-
- it('should validate response data', async () => {
- const invalidDataSetData = {
- id: '292', // Should be number
- pieces: 'not-array', // Should be array
- nextChallengeEpoch: 'soon', // Should be number
- }
-
- server.use(
- http.get('http://pdp.local/pdp/data-sets/292', async () => {
- return HttpResponse.json(invalidDataSetData, {
- status: 200,
- })
- })
- )
-
- try {
- await pdpServer.getDataSet(292)
- assert.fail('Should have thrown error for invalid response data')
- } catch (error) {
- assert.include((error as Error).message, 'Invalid data set data response format')
+ assert.instanceOf(error, GetDataSetError)
+ assert.equal(error.shortMessage, 'Failed to get data set.')
+ assert.equal(error.details, 'Service Provider PDP\nDatabase error')
}
})
@@ -1164,7 +1302,7 @@ describe('PDPServer', () => {
await pdpServer.getDataSet(292)
assert.fail('Should have thrown error for invalid CID in response')
} catch (error) {
- assert.include((error as Error).message, 'Invalid data set data response format')
+ assert.include((error as Error).message, 'Invalid CID string: invalid-cid-format')
}
})
})
diff --git a/packages/synapse-sdk/src/test/rand.test.ts b/packages/synapse-sdk/src/test/rand.test.ts
new file mode 100644
index 00000000..fcb44380
--- /dev/null
+++ b/packages/synapse-sdk/src/test/rand.test.ts
@@ -0,0 +1,78 @@
+/* globals describe it */
+import { assert } from 'chai'
+import { fallbackRandIndex, fallbackRandU256, randIndex, randU256 } from '../utils/rand.ts'
+
+const randIndexMethods = [randIndex, fallbackRandIndex]
+randIndexMethods.forEach((randIndexMethod) => {
+ describe(randIndexMethod.name, () => {
+ it('should return 0 for length 1', () => {
+ for (let i = 0; i < 32; i++) {
+ assert.equal(0, randIndexMethod(1))
+ }
+ })
+ it('returns both 0 and 1 for length 2', () => {
+ const counts = [0, 0]
+ for (let i = 0; i < 32; i++) {
+ counts[randIndexMethod(counts.length)]++
+ }
+ // this test can fail probabilistically but the probability is low
+ // each bit should be independent with 50% likelihood
+ // the probability of getting the same index N times is 2**(1-N)
+ // so if this test fails, the 50% assumption is likely wrong
+ assert.isAtLeast(counts[0], 1)
+ assert.isAtLeast(counts[1], 1)
+ })
+ it('has at least 10 random bits', () => {
+ const counts = []
+ for (let i = 0; i < 10; i++) {
+ counts.push([0, 0])
+ }
+ for (let i = 0; i < 32; i++) {
+ let index = randIndexMethod(1024)
+ assert.isAtLeast(index, 0)
+ assert.isAtMost(index, 1023)
+ for (let j = 0; j < 10; j++) {
+ counts[j][index & 1]++
+ index >>= 1
+ }
+ assert.equal(index, 0)
+ }
+ // this test can fail probabilistically but the probability is low
+ // each bit should be independent with 50% likelihood
+ // the probability of getting the same bitvalue N times is 2**(1-N)
+ // so if this test fails, the 50% assumption is likely wrong
+ for (let i = 0; i < 10; i++) {
+ assert.isAtLeast(counts[i][0], 1)
+ assert.isAtLeast(counts[i][1], 1)
+ }
+ })
+ })
+})
+
+const randU256Methods = [randU256, fallbackRandU256]
+randU256Methods.forEach((randU256Method) => {
+ describe(randU256Method.name, () => {
+ it('has 256 random bits', () => {
+ const counts = []
+ for (let i = 0; i < 256; i++) {
+ counts.push([0, 0])
+ }
+ for (let j = 0; j < 32; j++) {
+ let rand = randU256Method()
+ for (let i = 0; i < 256; i++) {
+ counts[i][Number(rand & 1n)]++
+ rand >>= 1n
+ }
+ assert.equal(rand, 0n)
+ }
+ // this test can fail probabilistically but the probability is low
+ // each bit should be independent with 50% likelihood
+ // the probability of getting the same bitvalue N times is 2**(1-N)
+ // so if this test fails, the 50% assumption is likely wrong
+ for (let i = 0; i < 256; i++) {
+ assert.isAtLeast(counts[i][0], 1)
+ assert.isAtLeast(counts[i][1], 1)
+ }
+ })
+ })
+})
diff --git a/packages/synapse-sdk/src/test/retriever-chain.test.ts b/packages/synapse-sdk/src/test/retriever-chain.test.ts
index 650e2c4b..cdfc90eb 100644
--- a/packages/synapse-sdk/src/test/retriever-chain.test.ts
+++ b/packages/synapse-sdk/src/test/retriever-chain.test.ts
@@ -84,10 +84,9 @@ const mockDataSet: EnhancedDataSetInfo = {
payee: mockProvider1.serviceProvider,
serviceProvider: mockProvider1.serviceProvider,
commissionBps: 100,
- clientDataSetId: 1,
+ clientDataSetId: 1n,
pdpEndEpoch: 0,
providerId: 1,
- cdnEndEpoch: 0,
paymentEndEpoch: 0,
withCDN: false,
pdpVerifierDataSetId: 123,
@@ -95,6 +94,7 @@ const mockDataSet: EnhancedDataSetInfo = {
currentPieceCount: 5,
isLive: true,
isManaged: true,
+ dataSetId: 1,
metadata: {},
}
@@ -202,7 +202,7 @@ describe('ChainRetriever', () => {
payer: '0xClient',
payee: '0xProvider1',
commissionBps: 100,
- clientDataSetId: 1,
+ clientDataSetId: 1n,
paymentEndEpoch: 0,
providerId: 1,
isLive: true,
@@ -215,7 +215,7 @@ describe('ChainRetriever', () => {
payer: '0xClient',
payee: '0xProvider2',
commissionBps: 100,
- clientDataSetId: 2,
+ clientDataSetId: 2n,
paymentEndEpoch: 0,
providerId: 2,
isLive: true,
diff --git a/packages/synapse-sdk/src/test/sp-registry-service.test.ts b/packages/synapse-sdk/src/test/sp-registry-service.test.ts
index bf91f663..ab5624b5 100644
--- a/packages/synapse-sdk/src/test/sp-registry-service.test.ts
+++ b/packages/synapse-sdk/src/test/sp-registry-service.test.ts
@@ -26,31 +26,40 @@ describe('SPRegistryService', () => {
getProviderByAddress: async (address: string) => {
if (address.toLowerCase() === mockProviderAddress.toLowerCase()) {
return {
- serviceProvider: mockProviderAddress,
- payee: mockProviderAddress,
- name: 'Test Provider',
- description: 'A test storage provider',
- isActive: true,
+ providerId: 0n,
+ info: {
+ serviceProvider: mockProviderAddress,
+ payee: mockProviderAddress,
+ name: 'Test Provider',
+ description: 'A test storage provider',
+ isActive: true,
+ },
}
}
// Return zero address for non-existent provider
return {
- serviceProvider: ethers.ZeroAddress,
- payee: ethers.ZeroAddress,
- name: '',
- description: '',
- isActive: false,
+ providerId: 0n,
+ info: {
+ serviceProvider: ethers.ZeroAddress,
+ payee: ethers.ZeroAddress,
+ name: '',
+ description: '',
+ isActive: false,
+ },
}
},
getProvider: async (id: number) => {
if (id === 1) {
return {
- id: BigInt(1),
- serviceProvider: mockProviderAddress,
- payee: mockProviderAddress,
- name: 'Test Provider',
- description: 'A test storage provider',
- isActive: true,
+ providerId: 1,
+ info: {
+ id: BigInt(1),
+ serviceProvider: mockProviderAddress,
+ payee: mockProviderAddress,
+ name: 'Test Provider',
+ description: 'A test storage provider',
+ isActive: true,
+ },
}
}
throw new Error('Provider not found')
diff --git a/packages/synapse-sdk/src/test/synapse.test.ts b/packages/synapse-sdk/src/test/synapse.test.ts
index 2d06cb43..31fec3e2 100644
--- a/packages/synapse-sdk/src/test/synapse.test.ts
+++ b/packages/synapse-sdk/src/test/synapse.test.ts
@@ -461,12 +461,14 @@ describe('Synapse', () => {
...presets.basic.serviceRegistry,
getProviderByAddress: () => [
{
- serviceProvider: ADDRESSES.zero,
- payee: ADDRESSES.zero,
- name: '',
- description: '',
- isActive: false,
providerId: 0n,
+ info: {
+ serviceProvider: ADDRESSES.zero,
+ payee: ADDRESSES.zero,
+ name: '',
+ description: '',
+ isActive: false,
+ },
},
],
},
@@ -707,23 +709,28 @@ describe('Synapse', () => {
if (data[0] === 1n) {
return [
{
- serviceProvider: ADDRESSES.serviceProvider1,
- payee: ADDRESSES.payee1,
- isActive: true,
- name: 'Test Provider',
- description: 'Test Provider',
providerId: 1n,
+ info: {
+ serviceProvider: ADDRESSES.serviceProvider1,
+ payee: ADDRESSES.payee1,
+ isActive: true,
+ name: 'Test Provider',
+ description: 'Test Provider',
+ },
},
]
}
return [
{
- serviceProvider: ADDRESSES.zero,
- payee: ADDRESSES.zero,
- isActive: false,
- name: '',
- description: '',
providerId: 0n,
+ info: {
+ serviceProvider: ADDRESSES.zero,
+ payee: ADDRESSES.zero,
+ isActive: false,
+ name: '',
+ description: '',
+ providerId: 0n,
+ },
},
]
},
diff --git a/packages/synapse-sdk/src/test/test-utils.ts b/packages/synapse-sdk/src/test/test-utils.ts
index 9c79f9b9..5cf2a96f 100644
--- a/packages/synapse-sdk/src/test/test-utils.ts
+++ b/packages/synapse-sdk/src/test/test-utils.ts
@@ -141,8 +141,8 @@ export function createMockProvider(chainId: number = 314159): ethers.Provider {
if (data?.startsWith('0xd39b33ab') === true) {
return ethers.AbiCoder.defaultAbiCoder().encode(['address'], [CONTRACT_ADDRESSES.USDFC.calibration])
}
- // filCDNBeneficiaryAddress() - function selector: 0xce4f8d8b
- if (data?.startsWith('0xce4f8d8b') === true) {
+ // filBeamBeneficiaryAddress() - function selector: 0xdd6979bf
+ if (data?.startsWith('0xdd6979bf') === true) {
return ethers.AbiCoder.defaultAbiCoder().encode(['address'], ['0x0000000000000000000000000000000000000000'])
}
// viewContractAddress() - function selector: 0x7a9ebc15
@@ -273,20 +273,20 @@ export function createMockProvider(chainId: number = 314159): ethers.Provider {
TIME_CONSTANTS.EPOCHS_PER_MONTH, // maxLockupPeriod (30 days)
])
}
- // Mock getRailsForPayerAndToken response - function selector: 0x9b85e253
- if (data.includes('9b85e253') === true) {
+ // Mock getRailsForPayerAndToken response - function selector: 0x007b5fd1
+ if (data.includes('007b5fd1') === true) {
const paymentsInterface = new ethers.Interface(CONTRACT_ABIS.PAYMENTS)
const rails = [
{ railId: 1n, isTerminated: false, endEpoch: 0n },
{ railId: 2n, isTerminated: true, endEpoch: 999999n },
]
- return paymentsInterface.encodeFunctionResult('getRailsForPayerAndToken', [rails])
+ return paymentsInterface.encodeFunctionResult('getRailsForPayerAndToken', [rails, 2, 2])
}
- // Mock getRailsForPayeeAndToken response - function selector: 0x2ecfb2bf
- if (data.includes('2ecfb2bf') === true) {
+ // Mock getRailsForPayeeAndToken response - function selector: 0x7f7562fa
+ if (data.includes('7f7562fa') === true) {
const paymentsInterface = new ethers.Interface(CONTRACT_ABIS.PAYMENTS)
const rails = [{ railId: 3n, isTerminated: false, endEpoch: 0n }]
- return paymentsInterface.encodeFunctionResult('getRailsForPayeeAndToken', [rails])
+ return paymentsInterface.encodeFunctionResult('getRailsForPayeeAndToken', [rails, 2, 2])
}
// Mock settleRail response - function selector: 0xbcd40bf8
if (data.includes('bcd40bf8') === true) {
@@ -295,6 +295,7 @@ export function createMockProvider(chainId: number = 314159): ethers.Provider {
ethers.parseUnits('100', 18), // totalSettledAmount
ethers.parseUnits('95', 18), // totalNetPayeeAmount
ethers.parseUnits('5', 18), // totalOperatorCommission
+ ethers.parseUnits('1', 18), // totalNetworkFee
1000000n, // finalSettledEpoch
'Settlement successful', // note
])
@@ -627,13 +628,6 @@ export function setupProviderRegistryMocks(
returnData: ethers.AbiCoder.defaultAbiCoder().encode(['address'], [CONTRACT_ADDRESSES.USDFC.calibration]),
}
}
- // Mock filCDNAddress
- if (callData.startsWith('0xf699dd7e')) {
- return {
- success: true,
- returnData: ethers.AbiCoder.defaultAbiCoder().encode(['address'], [ethers.ZeroAddress]),
- }
- }
// Mock viewContractAddress
if (callData.startsWith('0x7a9ebc15')) {
return {
@@ -655,8 +649,8 @@ export function setupProviderRegistryMocks(
// Handle calls to WarmStorageView contract for getApprovedProviders
if (target === MOCK_ADDRESSES.WARM_STORAGE_VIEW.toLowerCase()) {
- // Mock getApprovedProviders() - returns array of provider IDs
- if (callData.startsWith('0x266afe1b')) {
+ // Mock getApprovedProviders(uint256,uint256) - returns array of provider IDs
+ if (callData.startsWith('0x7709a7f7')) {
return {
success: true,
returnData: ethers.AbiCoder.defaultAbiCoder().encode(['uint256[]'], [approvedIds.map(BigInt)]),
@@ -671,15 +665,30 @@ export function setupProviderRegistryMocks(
const provider = providers.find((p) => p.id === providerId)
if (provider) {
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(
- ['tuple(address serviceProvider, address payee, string name, string description, bool isActive)'],
- [[provider.serviceProvider, provider.payee, provider.name, provider.description || '', provider.active]]
+ [
+ 'tuple(uint256 providerId, tuple(address serviceProvider, address payee, string name, string description, bool isActive) info)',
+ ],
+ [
+ [
+ providerId,
+ [
+ provider.serviceProvider,
+ provider.payee,
+ provider.name,
+ provider.description || '',
+ provider.active,
+ ],
+ ],
+ ]
)
return { success: true, returnData: encoded }
}
// Return empty provider
const encoded = ethers.AbiCoder.defaultAbiCoder().encode(
- ['tuple(address serviceProvider, address payee, string name, string description, bool isActive)'],
- [[ethers.ZeroAddress, ethers.ZeroAddress, '', '', false]]
+ [
+ 'tuple(uint256 providerId, tuple(address serviceProvider, address payee, string name, string description, bool isActive) info)',
+ ],
+ [[0n, [ethers.ZeroAddress, ethers.ZeroAddress, '', '', false]]]
)
return { success: true, returnData: encoded }
}
@@ -732,7 +741,7 @@ export function setupProviderRegistryMocks(
}
// Mock getApprovedProviders() - returns array of provider IDs (WarmStorageView)
- if (data?.startsWith('0x266afe1b')) {
+ if (data?.startsWith('0x7709a7f7')) {
return ethers.AbiCoder.defaultAbiCoder().encode(['uint256[]'], [approvedIds.map(BigInt)])
}
@@ -745,14 +754,23 @@ export function setupProviderRegistryMocks(
const provider = providers.find((p) => p.id === providerId)
if (provider) {
return ethers.AbiCoder.defaultAbiCoder().encode(
- ['tuple(address serviceProvider, address payee, string name, string description, bool isActive)'],
- [[provider.serviceProvider, provider.payee, provider.name, provider.description || '', provider.active]]
+ [
+ 'tuple(uint256 providerId, tuple(address serviceProvider, address payee, string name, string description, bool isActive) info)',
+ ],
+ [
+ [
+ providerId,
+ [provider.serviceProvider, provider.payee, provider.name, provider.description || '', provider.active],
+ ],
+ ]
)
}
// Return null provider (zero address indicates not found)
return ethers.AbiCoder.defaultAbiCoder().encode(
- ['tuple(address serviceProvider, address payee, string name, string description, bool isActive)'],
- [[ethers.ZeroAddress, ethers.ZeroAddress, '', '', false]]
+ [
+ 'tuple(uint256 providerId, tuple(address serviceProvider, address payee, string name, string description, bool isActive) info)',
+ ],
+ [[0n, [ethers.ZeroAddress, ethers.ZeroAddress, '', '', false]]]
)
}
@@ -849,14 +867,23 @@ export function setupProviderRegistryMocks(
const provider = providers.find((p) => p.serviceProvider.toLowerCase() === addressParam.toLowerCase())
if (provider) {
return ethers.AbiCoder.defaultAbiCoder().encode(
- ['tuple(address serviceProvider, address payee, string name, string description, bool isActive)'],
- [[provider.serviceProvider, provider.payee, provider.name, provider.description || '', provider.active]]
+ [
+ 'tuple(uint256 providerId, tuple(address serviceProvider, address payee, string name, string description, bool isActive) info)',
+ ],
+ [
+ [
+ provider.id,
+ [provider.serviceProvider, provider.payee, provider.name, provider.description || '', provider.active],
+ ],
+ ]
)
}
// Return zero address struct for not found
return ethers.AbiCoder.defaultAbiCoder().encode(
- ['tuple(address serviceProvider, address payee, string name, string description, bool isActive)'],
- [[ethers.ZeroAddress, ethers.ZeroAddress, '', '', false]]
+ [
+ 'tuple(uint256 providerId, tuple(address serviceProvider, address payee, string name, string description, bool isActive) info)',
+ ],
+ [[0n, [ethers.ZeroAddress, ethers.ZeroAddress, '', '', false]]]
)
}
diff --git a/packages/synapse-sdk/src/test/warm-storage-service.test.ts b/packages/synapse-sdk/src/test/warm-storage-service.test.ts
index 5dfaf63c..f94715c1 100644
--- a/packages/synapse-sdk/src/test/warm-storage-service.test.ts
+++ b/packages/synapse-sdk/src/test/warm-storage-service.test.ts
@@ -94,10 +94,10 @@ describe('WarmStorageService', () => {
payee: '0x2345678901234567890123456789012345678901',
serviceProvider: '0x3456789012345678901234567890123456789012',
commissionBps: 100,
- clientDataSetId: 5,
+ clientDataSetId: 5n,
pdpEndEpoch: 0,
providerId: 1,
- cdnEndEpoch: 0,
+ dataSetId: BigInt(dataSetId),
}
// Use the Interface to encode the return data properly
return viewInterface.encodeFunctionResult('getDataSet', [dataSetInfo])
@@ -111,7 +111,7 @@ describe('WarmStorageService', () => {
assert.equal(result?.cacheMissRailId, 457)
assert.equal(result?.cdnRailId, 458)
assert.equal(result?.payer, '0x1234567890123456789012345678901234567890')
- assert.equal(result?.clientDataSetId, 5)
+ assert.equal(result?.clientDataSetId, 5n)
})
it('should throw for non-existent data set', async () => {
@@ -130,10 +130,10 @@ describe('WarmStorageService', () => {
payee: ethers.ZeroAddress,
serviceProvider: ethers.ZeroAddress,
commissionBps: 0,
- clientDataSetId: 0,
+ clientDataSetId: 0n,
pdpEndEpoch: 0,
providerId: 0,
- cdnEndEpoch: 0,
+ dataSetId: BigInt(dataSetId),
}
// Use the Interface to encode the return data properly
return viewInterface.encodeFunctionResult('getDataSet', [emptyDataSet])
@@ -206,6 +206,7 @@ describe('WarmStorageService', () => {
if (data?.startsWith('0x967c6f21') === true) {
// Return two data sets
const dataSet1 = {
+ id: 1n,
pdpRailId: 123n,
cacheMissRailId: 0n,
cdnRailId: 0n,
@@ -218,6 +219,7 @@ describe('WarmStorageService', () => {
}
const dataSet2 = {
+ id: 2n,
pdpRailId: 456n,
cacheMissRailId: 457n,
cdnRailId: 458n, // Has CDN
@@ -242,7 +244,7 @@ describe('WarmStorageService', () => {
dataSet1.clientDataSetId,
dataSet1.paymentEndEpoch, // pdpEndEpoch
dataSet1.providerId,
- 0, // cdnEndEpoch
+ dataSet1.id,
],
[
dataSet2.pdpRailId,
@@ -255,7 +257,7 @@ describe('WarmStorageService', () => {
dataSet2.clientDataSetId,
dataSet2.paymentEndEpoch, // pdpEndEpoch
dataSet2.providerId,
- 0, // cdnEndEpoch
+ dataSet2.id,
],
]
@@ -274,7 +276,7 @@ describe('WarmStorageService', () => {
assert.equal(dataSets[0].payer.toLowerCase(), '0x1234567890123456789012345678901234567890'.toLowerCase())
assert.equal(dataSets[0].payee.toLowerCase(), '0xabcdef1234567890123456789012345678901234'.toLowerCase())
assert.equal(dataSets[0].commissionBps, 100)
- assert.equal(dataSets[0].clientDataSetId, 0)
+ assert.equal(dataSets[0].clientDataSetId, 0n)
assert.equal(dataSets[0].cdnRailId, 0) // No CDN
// Check second data set
@@ -282,7 +284,7 @@ describe('WarmStorageService', () => {
assert.equal(dataSets[1].payer.toLowerCase(), '0x1234567890123456789012345678901234567890'.toLowerCase())
assert.equal(dataSets[1].payee.toLowerCase(), '0x9876543210987654321098765432109876543210'.toLowerCase())
assert.equal(dataSets[1].commissionBps, 200)
- assert.equal(dataSets[1].clientDataSetId, 1)
+ assert.equal(dataSets[1].clientDataSetId, 1n)
assert.isAbove(dataSets[1].cdnRailId, 0) // Has CDN
})
@@ -344,10 +346,10 @@ describe('WarmStorageService', () => {
payee: '0xabcdef1234567890123456789012345678901234',
serviceProvider: '0xabcdef1234567890123456789012345678901234',
commissionBps: 100,
- clientDataSetId: 0,
+ clientDataSetId: 0n,
pdpEndEpoch: 0,
providerId: 1,
- cdnEndEpoch: 0,
+ dataSetId: 242n,
}
return viewInterface.encodeFunctionResult('getDataSet', [dataSetInfo])
}
@@ -419,10 +421,10 @@ describe('WarmStorageService', () => {
serviceProvider:
id === 242 ? '0xabc1234567890123456789012345678901234567' : '0xdef1234567890123456789012345678901234567',
commissionBps: 100,
- clientDataSetId: id === 242 ? 0 : 1,
+ clientDataSetId: id === 242 ? 0n : 1n,
pdpEndEpoch: 0,
providerId: id === 242 ? 1 : 2,
- cdnEndEpoch: 0,
+ dataSetId: BigInt(id),
})
const id = dataSetIdHex === ethers.zeroPadValue('0xf2', 32).slice(2) ? 242 : 243
return viewInterface.encodeFunctionResult('getDataSet', [baseInfo(id)])
@@ -508,10 +510,10 @@ describe('WarmStorageService', () => {
payee: '0xabc1234567890123456789012345678901234567',
serviceProvider: '0xabc1234567890123456789012345678901234567',
commissionBps: 100,
- clientDataSetId: 0,
+ clientDataSetId: 0n,
pdpEndEpoch: 0,
providerId: 1,
- cdnEndEpoch: 0,
+ dataSetId: 242n,
}
return viewInterface.encodeFunctionResult('getDataSet', [info])
}
@@ -567,7 +569,7 @@ describe('WarmStorageService', () => {
3n, // clientDataSetId
0n, // pdpEndEpoch
1n, // providerId
- 0n, // cdnEndEpoch
+ BigInt(dataSetId),
]
return viewInterface.encodeFunctionResult('getClientDataSets', [[dataSet]])
}
@@ -585,7 +587,7 @@ describe('WarmStorageService', () => {
clientDataSetId: 0n, // expecting 0
pdpEndEpoch: 0n,
providerId: 1n,
- cdnEndEpoch: 0n,
+ dataSetId: BigInt(dataSetId),
}
return viewInterface.encodeFunctionResult('getDataSet', [info])
}
@@ -597,7 +599,7 @@ describe('WarmStorageService', () => {
const addPiecesInfo = await warmStorageService.getAddPiecesInfo(dataSetId)
assert.equal(addPiecesInfo.nextPieceId, 5)
- assert.equal(addPiecesInfo.clientDataSetId, 0)
+ assert.equal(addPiecesInfo.clientDataSetId, 0n)
assert.equal(addPiecesInfo.currentPieceCount, 5) // Matches nextPieceId like master
})
@@ -624,7 +626,7 @@ describe('WarmStorageService', () => {
3n, // clientDataSetId
0n, // pdpEndEpoch
1n, // providerId
- 0n, // cdnEndEpoch
+ BigInt(dataSetId),
]
return viewInterface.encodeFunctionResult('getClientDataSets', [[dataSet]])
}
@@ -657,7 +659,6 @@ describe('WarmStorageService', () => {
clientDataSetId: 3n,
pdpEndEpoch: 0n,
providerId: 1n,
- cdnEndEpoch: 0n,
}
return viewInterface.encodeFunctionResult('getDataSet', [info])
}
@@ -677,23 +678,6 @@ describe('WarmStorageService', () => {
})
})
- describe('getNextClientDataSetId', () => {
- it('should return the next client dataset ID', async () => {
- const warmStorageService = await createWarmStorageService()
- cleanup = mockProviderWithView((data) => {
- // clientDataSetIDs mapping call
- if (data?.startsWith('0x196ed89b') === true) {
- return ethers.zeroPadValue('0x05', 32) // Return 5
- }
-
- return null
- })
-
- const nextId = await warmStorageService.getNextClientDataSetId(clientAddress)
- assert.equal(nextId, 5)
- })
- })
-
describe('verifyDataSetCreation', () => {
it('should verify successful data set creation', async () => {
const warmStorageService = await createWarmStorageService()
@@ -789,7 +773,7 @@ describe('WarmStorageService', () => {
cleanup = mockProviderWithView((data) => {
// getApprovedProviders selector
- if (data?.startsWith('0x266afe1b') === true) {
+ if (data?.startsWith('0x7709a7f7') === true) {
// Return array of provider IDs [1, 4, 7]
return viewInterface.encodeFunctionResult('getApprovedProviders', [[1n, 4n, 7n]])
}
@@ -808,7 +792,7 @@ describe('WarmStorageService', () => {
cleanup = mockProviderWithView((data) => {
// getApprovedProviders selector
- if (data?.startsWith('0x266afe1b') === true) {
+ if (data?.startsWith('0x7709a7f7') === true) {
// Return empty array
return viewInterface.encodeFunctionResult('getApprovedProviders', [[]])
}
@@ -979,7 +963,7 @@ describe('WarmStorageService', () => {
cleanup = mockProviderWithView((data) => {
// getApprovedProviders selector - return array with provider 4 at index 1
- if (data?.startsWith('0x266afe1b') === true) {
+ if (data?.startsWith('0x7709a7f7') === true) {
return viewInterface.encodeFunctionResult('getApprovedProviders', [[1n, 4n, 7n]])
}
return null
@@ -1014,7 +998,7 @@ describe('WarmStorageService', () => {
cleanup = mockProviderWithView((data) => {
// getApprovedProviders selector - return array without provider 99
- if (data?.startsWith('0x266afe1b') === true) {
+ if (data?.startsWith('0x7709a7f7') === true) {
return viewInterface.encodeFunctionResult('getApprovedProviders', [[1n, 4n, 7n]])
}
return null
@@ -1344,8 +1328,9 @@ describe('WarmStorageService', () => {
assert.exists(check.depositAmountNeeded)
assert.isTrue(check.depositAmountNeeded > 0n)
- // depositAmountNeeded should equal 10 days of costs (default lockup)
- const expectedDeposit = check.costs.perEpoch * BigInt(10) * BigInt(TIME_CONSTANTS.EPOCHS_PER_DAY)
+ // depositAmountNeeded should equal 30 days of costs (default lockup)
+ const expectedDeposit =
+ check.costs.perEpoch * TIME_CONSTANTS.DEFAULT_LOCKUP_DAYS * TIME_CONSTANTS.EPOCHS_PER_DAY
assert.equal(check.depositAmountNeeded.toString(), expectedDeposit.toString())
})
@@ -1389,27 +1374,27 @@ describe('WarmStorageService', () => {
return `0x${'0'.repeat(64)}`
}
- // Test with custom lockup period of 20 days
- const customLockupDays = 20
+ // Test with custom lockup period of 60 days
+ const customLockupDays = TIME_CONSTANTS.DEFAULT_LOCKUP_DAYS * 2n
const check = await warmStorageService.checkAllowanceForStorage(
Number(SIZE_CONSTANTS.GiB), // 1 GiB
false,
mockPaymentsService,
- customLockupDays
+ Number(customLockupDays)
)
// Verify depositAmountNeeded uses custom lockup period
- const expectedDeposit = check.costs.perEpoch * BigInt(customLockupDays) * BigInt(TIME_CONSTANTS.EPOCHS_PER_DAY)
+ const expectedDeposit = check.costs.perEpoch * customLockupDays * TIME_CONSTANTS.EPOCHS_PER_DAY
assert.equal(check.depositAmountNeeded.toString(), expectedDeposit.toString())
- // Compare with default (10 days) to ensure they're different
+ // Compare with default (30 days) to ensure they're different
const defaultCheck = await warmStorageService.checkAllowanceForStorage(
Number(SIZE_CONSTANTS.GiB), // 1 GiB
false,
mockPaymentsService
)
- // Custom should be exactly 2x default (20 days vs 10 days)
+ // Custom should be exactly 2x default (60 days vs 30 days)
assert.equal(check.depositAmountNeeded.toString(), (defaultCheck.depositAmountNeeded * 2n).toString())
})
})
@@ -2051,4 +2036,30 @@ describe('WarmStorageService', () => {
mockProvider.call = originalCall
})
})
+
+ describe('CDN Operations', () => {
+ it('should top up CDN payment rails (mock transaction)', async () => {
+ const dataSetId = 49
+ const warmStorageService = await createWarmStorageService()
+ const mockSigner = {
+ getAddress: async () => '0x1234567890123456789012345678901234567890',
+ } as any
+
+ // Mock the contract connection
+ const originalGetWarmStorageContract = (warmStorageService as any)._getWarmStorageContract
+ ;(warmStorageService as any)._getWarmStorageContract = () => ({
+ connect: () => ({
+ topUpCDNPaymentRails: async () => ({
+ hash: '0xmocktxhash',
+ wait: async () => ({ status: 1 }),
+ }),
+ }),
+ })
+
+ const tx = await warmStorageService.topUpCDNPaymentRails(mockSigner, dataSetId, 1n, 1n)
+ assert.equal(tx.hash, '0xmocktxhash')
+
+ ;(warmStorageService as any)._getWarmStorageContract = originalGetWarmStorageContract
+ })
+ })
})
diff --git a/packages/synapse-sdk/src/types.ts b/packages/synapse-sdk/src/types.ts
index 3ee48741..3c6125f5 100644
--- a/packages/synapse-sdk/src/types.ts
+++ b/packages/synapse-sdk/src/types.ts
@@ -209,15 +209,15 @@ export interface DataSetInfo {
/** Commission rate in basis points (dynamic based on CDN usage) */
commissionBps: number
/** Client's sequential dataset ID within this Warm Storage contract */
- clientDataSetId: number
+ clientDataSetId: bigint
/** Epoch when PDP payments end (0 if not terminated) */
pdpEndEpoch: number
/** Provider ID from the ServiceProviderRegistry */
providerId: number
- /** Epoch when CDN payments end (0 if not terminated) */
- cdnEndEpoch: number
// Legacy alias for backward compatibility
paymentEndEpoch?: number
+ /** PDP Data Set ID */
+ dataSetId: bigint | number
}
/**
@@ -262,6 +262,8 @@ export interface SettlementResult {
totalNetPayeeAmount: bigint
/** Commission amount for operator */
totalOperatorCommission: bigint
+ /** Payments contract network fee */
+ totalNetworkFee: bigint
/** Final epoch that was settled */
finalSettledEpoch: bigint
/** Note about the settlement */
@@ -331,6 +333,8 @@ export interface StorageCreationCallbacks {
export interface StorageServiceOptions {
/** Specific provider ID to use (optional) */
providerId?: number
+ /** Do not select any of these providers */
+ excludeProviderIds?: number[]
/** Specific provider address to use (optional) */
providerAddress?: string
/** Specific data set ID to use (optional) */
diff --git a/packages/synapse-sdk/src/utils/constants.ts b/packages/synapse-sdk/src/utils/constants.ts
index 70aa0ac1..4f6dc638 100644
--- a/packages/synapse-sdk/src/utils/constants.ts
+++ b/packages/synapse-sdk/src/utils/constants.ts
@@ -115,7 +115,7 @@ export const TIME_CONSTANTS = {
/**
* Default lockup period in days
*/
- DEFAULT_LOCKUP_DAYS: 10n,
+ DEFAULT_LOCKUP_DAYS: 30n,
} as const
/**
@@ -319,7 +319,7 @@ export const CONTRACT_ADDRESSES = {
*/
WARM_STORAGE: {
mainnet: '0x81DFD9813aDd354f03704F31419b0c6268d46232',
- calibration: '0x80617b65FD2EEa1D7fDe2B4F85977670690ed348',
+ calibration: '0xD3De778C05f89e1240ef70100Fb0d9e5b2eFD258',
} as const satisfies Record,
/**
diff --git a/packages/synapse-sdk/src/utils/index.ts b/packages/synapse-sdk/src/utils/index.ts
index 82f151d1..b75b0c5d 100644
--- a/packages/synapse-sdk/src/utils/index.ts
+++ b/packages/synapse-sdk/src/utils/index.ts
@@ -5,3 +5,4 @@ export { createError } from './errors.ts'
export { combineMetadata, metadataMatches } from './metadata.ts'
export { getFilecoinNetworkType } from './network.ts'
export { constructFindPieceUrl, constructPieceUrl } from './piece.ts'
+export { randIndex, randU256 } from './rand.ts'
diff --git a/packages/synapse-sdk/src/utils/rand.ts b/packages/synapse-sdk/src/utils/rand.ts
new file mode 100644
index 00000000..e682615a
--- /dev/null
+++ b/packages/synapse-sdk/src/utils/rand.ts
@@ -0,0 +1,47 @@
+const crypto = globalThis.crypto
+
+export function fallbackRandU256(): bigint {
+ let result = 0n
+ for (let i = 0; i < 32; i++) {
+ result <<= 8n
+ result |= BigInt(fallbackRandIndex(256))
+ }
+ return result
+}
+
+/**
+ * @returns a random unsigned big integer between `0` and `2**256-1` inclusive
+ */
+export function randU256(): bigint {
+ if (crypto?.getRandomValues != null) {
+ const randU64s = new BigUint64Array(4)
+ crypto.getRandomValues(randU64s)
+ let result = 0n
+ randU64s.forEach((randU64) => {
+ result <<= 64n
+ result |= randU64
+ })
+ return result
+ } else {
+ return fallbackRandU256()
+ }
+}
+
+export function fallbackRandIndex(length: number): number {
+ return Math.floor(Math.random() * length)
+}
+
+/**
+ * Provides a random index into an array of supplied length (0 <= index < length)
+ * @param length - exclusive upper boundary
+ * @returns a valid index
+ */
+export function randIndex(length: number): number {
+ if (crypto?.getRandomValues != null) {
+ const randomBytes = new Uint32Array(1)
+ crypto.getRandomValues(randomBytes)
+ return randomBytes[0] % length
+ } else {
+ return fallbackRandIndex(length)
+ }
+}
diff --git a/packages/synapse-sdk/src/warm-storage/service.ts b/packages/synapse-sdk/src/warm-storage/service.ts
index e1544757..df95959d 100644
--- a/packages/synapse-sdk/src/warm-storage/service.ts
+++ b/packages/synapse-sdk/src/warm-storage/service.ts
@@ -6,6 +6,7 @@
* - Service provider registration and management
* - Client dataset ID tracking
* - Data set creation verification
+ * - CDN service management
*
* @example
* ```typescript
@@ -40,7 +41,7 @@ export interface AddPiecesInfo {
/** The next piece ID to use when adding pieces */
nextPieceId: number
/** The client dataset ID for this data set */
- clientDataSetId: number
+ clientDataSetId: bigint
/** Current number of pieces in the data set */
currentPieceCount: number
}
@@ -114,7 +115,7 @@ export class WarmStorageService {
pdpVerifier: string
payments: string
usdfcToken: string
- filCDNBeneficiary: string
+ filBeamBeneficiary: string
viewContract: string
serviceProviderRegistry: string
sessionKeyRegistry: string
@@ -130,7 +131,7 @@ export class WarmStorageService {
pdpVerifier: string
payments: string
usdfcToken: string
- filCDNBeneficiary: string
+ filBeamBeneficiary: string
viewContract: string
serviceProviderRegistry: string
sessionKeyRegistry: string
@@ -176,7 +177,7 @@ export class WarmStorageService {
{
target: warmStorageAddress,
allowFailure: false,
- callData: iface.encodeFunctionData('filCDNBeneficiaryAddress'),
+ callData: iface.encodeFunctionData('filBeamBeneficiaryAddress'),
},
{
target: warmStorageAddress,
@@ -201,7 +202,7 @@ export class WarmStorageService {
pdpVerifier: iface.decodeFunctionResult('pdpVerifierAddress', results[0].returnData)[0],
payments: iface.decodeFunctionResult('paymentsContractAddress', results[1].returnData)[0],
usdfcToken: iface.decodeFunctionResult('usdfcTokenAddress', results[2].returnData)[0],
- filCDNBeneficiary: iface.decodeFunctionResult('filCDNBeneficiaryAddress', results[3].returnData)[0],
+ filBeamBeneficiary: iface.decodeFunctionResult('filBeamBeneficiaryAddress', results[3].returnData)[0],
viewContract: iface.decodeFunctionResult('viewContractAddress', results[4].returnData)[0],
serviceProviderRegistry: iface.decodeFunctionResult('serviceProviderRegistry', results[5].returnData)[0],
sessionKeyRegistry: iface.decodeFunctionResult('sessionKeyRegistry', results[6].returnData)[0],
@@ -303,10 +304,10 @@ export class WarmStorageService {
payee: ds.payee,
serviceProvider: ds.serviceProvider,
commissionBps: Number(ds.commissionBps),
- clientDataSetId: Number(ds.clientDataSetId),
+ clientDataSetId: ds.clientDataSetId,
pdpEndEpoch: Number(ds.pdpEndEpoch),
providerId: Number(ds.providerId),
- cdnEndEpoch: Number(ds.cdnEndEpoch),
+ dataSetId,
}
}
@@ -329,10 +330,9 @@ export class WarmStorageService {
payee: ds.payee,
serviceProvider: ds.serviceProvider,
commissionBps: Number(ds.commissionBps),
- clientDataSetId: Number(ds.clientDataSetId),
+ clientDataSetId: ds.clientDataSetId,
pdpEndEpoch: Number(ds.pdpEndEpoch),
providerId: Number(ds.providerId),
- cdnEndEpoch: Number(ds.cdnEndEpoch),
}))
} catch (error) {
throw new Error(`Failed to get client data sets: ${error instanceof Error ? error.message : String(error)}`)
@@ -435,11 +435,9 @@ export class WarmStorageService {
)
}
- const clientDataSetId = Number(dataSetInfo.clientDataSetId)
-
return {
nextPieceId: Number(nextPieceId),
- clientDataSetId,
+ clientDataSetId: dataSetInfo.clientDataSetId,
currentPieceCount: Number(nextPieceId),
}
} catch (error) {
@@ -447,27 +445,6 @@ export class WarmStorageService {
}
}
- /**
- * Get the next client dataset ID for a given client
- * This reads the current counter from the WarmStorage contract
- * @param clientAddress - The client's wallet address
- * @returns next client dataset ID that will be assigned by this WarmStorage contract
- */
- async getNextClientDataSetId(clientAddress: string): Promise {
- try {
- const viewContract = this._getWarmStorageViewContract()
-
- // Get the current clientDataSetIDs counter for this client in this WarmStorage contract
- // This is the value that will be used for the next data set creation
- const currentCounter = await viewContract.clientDataSetIDs(clientAddress)
-
- // Return the current counter value (it will be incremented during data set creation)
- return Number(currentCounter)
- } catch (error) {
- throw new Error(`Failed to get next client dataset ID: ${error instanceof Error ? error.message : String(error)}`)
- }
- }
-
/**
* Verify that a data set creation transaction was successful
* This checks both the transaction status and on-chain data set state
@@ -1032,7 +1009,7 @@ export class WarmStorageService {
// First, we need to find the index of this provider in the array
const viewContract = this._getWarmStorageViewContract()
- const approvedIds = await viewContract.getApprovedProviders()
+ const approvedIds = await viewContract.getApprovedProviders(0n, 0n)
const index = approvedIds.findIndex((id: bigint) => Number(id) === providerId)
if (index === -1) {
@@ -1048,7 +1025,7 @@ export class WarmStorageService {
*/
async getApprovedProviderIds(): Promise {
const viewContract = this._getWarmStorageViewContract()
- const providerIds = await viewContract.getApprovedProviders()
+ const providerIds = await viewContract.getApprovedProviders(0n, 0n)
return providerIds.map((id: bigint) => Number(id))
}
@@ -1103,4 +1080,32 @@ export class WarmStorageService {
const window = await viewContract.challengeWindow()
return Number(window)
}
+ /**
+ * Increments the fixed locked-up amounts for CDN payment rails.
+ *
+ * This method tops up the prepaid balance for CDN services by adding to the existing
+ * lockup amounts. Both CDN and cache miss rails can be incremented independently.
+ *
+ * @param dataSetId - The ID of the data set
+ * @param cdnAmountToAdd - Amount to add to the CDN rail lockup
+ * @param cacheMissAmountToAdd - Amount to add to the cache miss rail lockup
+ * @returns Transaction response
+ */
+ async topUpCDNPaymentRails(
+ signer: ethers.Signer,
+ dataSetId: number,
+ cdnAmountToAdd: bigint,
+ cacheMissAmountToAdd: bigint
+ ): Promise {
+ if (cdnAmountToAdd < 0n || cacheMissAmountToAdd < 0n) {
+ throw new Error('Top up amounts must be positive')
+ }
+ if (cdnAmountToAdd === 0n && cacheMissAmountToAdd === 0n) {
+ throw new Error('At least one top up amount must be >0')
+ }
+
+ const contract = this._getWarmStorageContract()
+ const contractWithSigner = contract.connect(signer) as ethers.Contract
+ return await contractWithSigner.topUpCDNPaymentRails(dataSetId, cdnAmountToAdd, cacheMissAmountToAdd)
+ }
}
diff --git a/packages/synapse-sdk/tsconfig.json b/packages/synapse-sdk/tsconfig.json
index 652d1e7f..caa2d4df 100644
--- a/packages/synapse-sdk/tsconfig.json
+++ b/packages/synapse-sdk/tsconfig.json
@@ -5,6 +5,11 @@
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"],
+ "references": [
+ {
+ "path": "../synapse-core"
+ }
+ ],
"typedocOptions": {
"entryPointStrategy": "resolve",
"entryPoints": [
diff --git a/packages/synapse-sdk/wagmi.config.ts b/packages/synapse-sdk/wagmi.config.ts
index c2e15168..f5b02b82 100644
--- a/packages/synapse-sdk/wagmi.config.ts
+++ b/packages/synapse-sdk/wagmi.config.ts
@@ -2,8 +2,9 @@ import { defineConfig } from '@wagmi/cli'
import { fetch } from '@wagmi/cli/plugins'
import type { Address } from 'viem'
-const GIT_REF = 'tags/alpha/calibnet/0x80617b65FD2EEa1D7fDe2B4F85977670690ed348-v2'
-const BASE_URL = `https://raw.githubusercontent.com/FilOzone/filecoin-services/refs/${GIT_REF}/service_contracts/abi`
+// GIT_REF can be one of: '', '' or 'tags/'
+const GIT_REF = 'c77dfedebae55078102b45564a59914dea5338b3'
+const BASE_URL = `https://raw.githubusercontent.com/FilOzone/filecoin-services/${GIT_REF.replace(/^(?![a-f0-9]{40}$)/, 'refs/')}/service_contracts/abi`
const config = defineConfig(() => {
const contracts = [
diff --git a/utils/README.md b/utils/README.md
index e2ba31ea..c0e81b4d 100644
--- a/utils/README.md
+++ b/utils/README.md
@@ -192,7 +192,7 @@ Comprehensive demonstration of the enhanced payment APIs in the Synapse SDK.
- **Balance**: USDFC deposited in the Payments contract for storage costs
- **Rate Allowance**: Maximum per-epoch payment rate a service can set
-- **Lockup Allowance**: Security deposit (10 days of storage) locked during rail creation
+- **Lockup Allowance**: Security deposit (30 days of storage) locked during rail creation
## Development Notes