diff --git a/packages/synapse-sdk/src/abis/gen.ts b/packages/synapse-sdk/src/abis/gen.ts index 842a5882d..76b19058d 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: [], @@ -379,6 +401,17 @@ export const filecoinWarmStorageServiceAbi = [ outputs: [], stateMutability: 'nonpayable', }, + { + type: 'function', + inputs: [ + { name: 'dataSetId', internalType: 'uint256', type: 'uint256' }, + { name: 'cdnAmount', internalType: 'uint256', type: 'uint256' }, + { name: 'cacheMissAmount', internalType: 'uint256', type: 'uint256' }, + ], + name: 'settleFilBeamPaymentRails', + outputs: [], + stateMutability: 'nonpayable', + }, { type: 'function', inputs: [ @@ -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', }, { @@ -478,6 +528,31 @@ 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: 'totalCdnLockup', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + { + name: 'totalCacheMissLockup', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'CDNPaymentRailsToppedUp', + }, { type: 'event', anonymous: false, @@ -694,7 +769,7 @@ export const filecoinWarmStorageServiceAbi = [ indexed: false, }, ], - name: 'FilCDNControllerChanged', + name: 'FilBeamControllerChanged', }, { type: 'event', @@ -930,6 +1005,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, @@ -956,11 +1052,41 @@ export const filecoinWarmStorageServiceAbi = [ ], name: 'ViewContractSet', }, + { + type: 'error', + inputs: [ + { + name: 'field', + internalType: 'enum Errors.AddressField', + type: 'uint8', + }, + ], + name: 'AddressAlreadySet', + }, { type: 'error', 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 +1114,13 @@ export const filecoinWarmStorageServiceAbi = [ ], name: 'ChallengeWindowTooEarly', }, + { + type: 'error', + inputs: [ + { name: 'clientDataSetId', internalType: 'uint256', type: 'uint256' }, + ], + name: 'ClientDataSetAlreadyRegistered', + }, { type: 'error', inputs: [ @@ -1047,12 +1180,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', @@ -1095,6 +1223,16 @@ export const filecoinWarmStorageServiceAbi = [ name: 'InvalidEpochRange', }, { type: 'error', inputs: [], name: 'InvalidInitialization' }, + { + type: 'error', + inputs: [{ name: 'length', internalType: 'uint256', type: 'uint256' }], + name: 'InvalidServiceDescriptionLength', + }, + { + type: 'error', + inputs: [{ name: 'length', internalType: 'uint256', type: 'uint256' }], + name: 'InvalidServiceNameLength', + }, { type: 'error', inputs: [ @@ -1111,6 +1249,11 @@ export const filecoinWarmStorageServiceAbi = [ ], name: 'InvalidSignatureLength', }, + { + type: 'error', + inputs: [{ name: 'dataSetId', internalType: 'uint256', type: 'uint256' }], + name: 'InvalidTopUpAmount', + }, { type: 'error', inputs: [], name: 'MaxProvingPeriodZero' }, { type: 'error', @@ -1176,7 +1319,7 @@ export const filecoinWarmStorageServiceAbi = [ { name: 'expected', internalType: 'address', type: 'address' }, { name: 'actual', internalType: 'address', type: 'address' }, ], - name: 'OnlyFilCDNControllerAllowed', + name: 'OnlyFilBeamControllerAllowed', }, { type: 'error', @@ -1186,14 +1329,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 +1344,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', }, @@ -1340,8 +1474,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 +1494,7 @@ export const filecoinWarmStorageServiceStateViewAbi = [ { type: 'function', inputs: [], - name: 'filCDNControllerAddress', + name: 'filBeamControllerAddress', outputs: [{ name: '', internalType: 'address', type: 'address' }], stateMutability: 'view', }, @@ -1386,13 +1523,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 +1554,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 +1567,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 +1580,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 +1593,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 +1619,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 +1683,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 +1744,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,13 +1786,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: [], @@ -1623,20 +1793,6 @@ export const pdpVerifierAbi = [ 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 +1821,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 +1839,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 +1850,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: 'rawSize', internalType: 'uint256', type: 'uint256' }], + name: 'calculateProofFeeForSize', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, { type: 'function', inputs: [ @@ -1763,6 +1903,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: [ @@ -1858,16 +2012,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 +2138,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 +2195,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 +2284,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 +2445,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 +2566,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 +2595,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,7 +2632,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' }, ], @@ -2430,7 +2643,73 @@ export const paymentsAbi = [ { type: 'function', inputs: [ - { name: 'token', internalType: 'address', type: 'address' }, + { 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: 'depositWithAuthorizationAndIncreaseOperatorApproval', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { 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 +2724,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 +2743,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 +2769,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 +2791,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 +2820,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 +2836,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 +2845,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 +2861,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 +2876,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 +2918,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 +2936,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 +2962,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 +2980,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 +2996,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 +3006,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 +3020,7 @@ export const paymentsAbi = [ inputs: [ { name: 'token', - internalType: 'address', + internalType: 'contract IERC20', type: 'address', indexed: true, }, @@ -2768,7 +3057,7 @@ export const paymentsAbi = [ inputs: [ { name: 'token', - internalType: 'address', + internalType: 'contract IERC20', type: 'address', indexed: true, }, @@ -2780,12 +3069,6 @@ export const paymentsAbi = [ type: 'uint256', indexed: false, }, - { - name: 'usedPermit', - internalType: 'bool', - type: 'bool', - indexed: false, - }, ], name: 'DepositRecorded', }, @@ -2795,7 +3078,7 @@ export const paymentsAbi = [ inputs: [ { name: 'token', - internalType: 'address', + internalType: 'contract IERC20', type: 'address', indexed: true, }, @@ -2857,7 +3140,7 @@ export const paymentsAbi = [ }, { name: 'token', - internalType: 'address', + internalType: 'contract IERC20', type: 'address', indexed: false, }, @@ -2960,6 +3243,12 @@ export const paymentsAbi = [ type: 'uint256', indexed: false, }, + { + name: 'networkFee', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, ], name: 'RailOneTimePaymentProcessed', }, @@ -3016,6 +3305,12 @@ export const paymentsAbi = [ type: 'uint256', indexed: false, }, + { + name: 'networkFee', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, { name: 'settledUpTo', internalType: 'uint256', @@ -3051,7 +3346,7 @@ export const paymentsAbi = [ inputs: [ { name: 'token', - internalType: 'address', + internalType: 'contract IERC20', type: 'address', indexed: true, }, @@ -3104,7 +3399,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 +3409,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 +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: 'required', internalType: 'uint256', type: 'uint256' }, { name: 'actual', internalType: 'uint256', type: 'uint256' }, @@ -3134,7 +3429,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 +3439,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 +3491,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 +3501,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 +3516,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 +3537,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 +3551,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 +3645,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 +3672,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 +3716,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 +3751,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' }], @@ -3729,11 +4037,6 @@ export const serviceProviderRegistryAbi = [ type: 'string', }, { name: 'isActive', internalType: 'bool', type: 'bool' }, - { - name: 'providerId', - internalType: 'uint256', - type: 'uint256', - }, ], }, { @@ -3892,16 +4195,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 +4230,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 +4272,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 +4361,6 @@ export const serviceProviderRegistryAbi = [ type: 'string', }, { name: 'isActive', internalType: 'bool', type: 'bool' }, - { - name: 'providerId', - internalType: 'uint256', - type: 'uint256', - }, ], }, { @@ -4137,7 +4501,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', }, @@ -4582,6 +4945,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 +4957,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 +4968,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 ba2f7e20b..f2feb4772 100644 --- a/packages/synapse-sdk/src/payments/service.ts +++ b/packages/synapse-sdk/src/payments/service.ts @@ -919,16 +919,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( @@ -1075,7 +1074,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), @@ -1105,7 +1104,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/server.ts b/packages/synapse-sdk/src/pdp/server.ts index 3b6e39857..160b66d35 100644 --- a/packages/synapse-sdk/src/pdp/server.ts +++ b/packages/synapse-sdk/src/pdp/server.ts @@ -182,7 +182,7 @@ export class PDPServer { * @returns Promise that resolves with transaction hash and status URL */ async createDataSet( - clientDataSetId: number, + clientDataSetId: number | bigint, payee: string, payer: string, metadata: MetadataEntry[], @@ -198,6 +198,7 @@ export class PDPServer { // This needs to match the DataSetCreateData struct in Warm Storage contract const extraData = this._encodeDataSetCreateData({ payer, + clientDataSetId, metadata, signature: authData.signature, }) @@ -669,20 +670,29 @@ export class PDPServer { * 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: number | 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/session/key.ts b/packages/synapse-sdk/src/session/key.ts index 06f56484c..22efcb275 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 fe30144ba..3854e6ae3 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 15f52945f..631866e51 100644 --- a/packages/synapse-sdk/src/storage/context.ts +++ b/packages/synapse-sdk/src/storage/context.ts @@ -30,6 +30,7 @@ import { SPRegistryService } from '../sp-registry/index.ts' import type { ProviderInfo } from '../sp-registry/types.ts' import type { Synapse } from '../synapse.ts' import type { + CreateContextsOptions, DownloadOptions, EnhancedDataSetInfo, MetadataEntry, @@ -55,6 +56,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 { @@ -171,6 +173,78 @@ export class StorageContext { this._pdpServer = new PDPServer(authHelper, provider.products.PDP.data.serviceURL) } + static async createContexts( + synapse: Synapse, + warmStorageService: WarmStorageService, + options: CreateContextsOptions = {} + ): Promise { + const count = options?.count ?? 2 + const resolutions: ProviderSelectionResult[] = [] + const clientAddress = await synapse.getClient().getAddress() + const registryAddress = warmStorageService.getServiceProviderRegistryAddress() + const spRegistry = new SPRegistryService(synapse.getProvider(), registryAddress) + const providerResolver = new ProviderResolver(warmStorageService, spRegistry) + if (options?.dataSetIds) { + for (const dataSetId of options.dataSetIds) { + const resolution = await StorageContext.resolveByDataSetId( + dataSetId, + warmStorageService, + providerResolver, + clientAddress, + { + withCDN: options.withCDN, + withIpni: options.withIpni, + dev: options.dev, + metadata: options.metadata, + } + ) + resolutions.push(resolution) + if (resolutions.length >= count) { + break + } + } + } + if (resolutions.length < count) { + if (options?.providerIds) { + for (const providerId of options.providerIds) { + const resolution = await StorageContext.resolveByProviderId( + clientAddress, + providerId, + options.metadata ?? {}, + warmStorageService, + providerResolver, + options.forceCreateDataSets + ) + resolutions.push(resolution) + if (resolutions.length >= count) { + break + } + } + } else if (options?.providerAddresses) { + for (const providerAddress of options.providerAddresses) { + const resolution = await StorageContext.resolveByProviderAddress( + providerAddress, + warmStorageService, + providerResolver, + clientAddress, + options.metadata ?? {}, + options.forceCreateDataSets + ) + resolutions.push(resolution) + if (resolutions.length >= count) { + break + } + } + } + } + return await Promise.all( + resolutions.map( + async (resolution) => + await StorageContext.createWithSelectedProvider(resolution, synapse, warmStorageService, options) + ) + ) + } + /** * Static factory method to create a StorageContext * Handles provider selection and data set selection/creation @@ -193,6 +267,15 @@ export class StorageContext { options ) + return await StorageContext.createWithSelectedProvider(resolution, synapse, warmStorageService, options) + } + + private static async createWithSelectedProvider( + resolution: ProviderSelectionResult, + synapse: Synapse, + warmStorageService: WarmStorageService, + options: StorageServiceOptions = {} + ): Promise { // Notify callback about provider selection try { options.callbacks?.onProviderSelected?.(resolution.provider) @@ -258,7 +341,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() @@ -441,8 +524,7 @@ export class StorageContext { providerResolver: ProviderResolver, options: StorageServiceOptions ): Promise { - const client = synapse.getClient() - const clientAddress = await client.getAddress() + const clientAddress = await synapse.getClient().getAddress() // Handle explicit data set ID selection (highest priority) if (options.dataSetId != null && options.forceCreateDataSet !== true) { @@ -488,7 +570,7 @@ export class StorageContext { requestedMetadata, warmStorageService, providerResolver, - client, + options.excludeProviderIds, options.forceCreateDataSet, options.withIpni, options.dev @@ -705,7 +787,7 @@ export class StorageContext { requestedMetadata: Record, warmStorageService: WarmStorageService, providerResolver: ProviderResolver, - signer: ethers.Signer, + excludeProviderIds?: number[], forceCreateDataSet?: boolean, withIpni?: boolean, dev?: boolean @@ -732,7 +814,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 +826,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 +867,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 +889,10 @@ 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 * @returns Selected provider */ private static async selectRandomProvider( providers: ProviderInfo[], - signer?: ethers.Signer, withIpni?: boolean, dev?: boolean ): Promise { @@ -823,34 +905,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 } } diff --git a/packages/synapse-sdk/src/storage/manager.ts b/packages/synapse-sdk/src/storage/manager.ts index d64d3ba04..6f569c100 100644 --- a/packages/synapse-sdk/src/storage/manager.ts +++ b/packages/synapse-sdk/src/storage/manager.ts @@ -25,6 +25,7 @@ import { asPieceCID, downloadAndValidate } from '../piece/index.ts' import { SPRegistryService } from '../sp-registry/index.ts' import type { Synapse } from '../synapse.ts' import type { + CreateContextsOptions, DownloadOptions, EnhancedDataSetInfo, PieceCID, @@ -231,6 +232,15 @@ export class StorageManager { return await StorageContext.performPreflightCheck(this._warmStorageService, this._synapse.payments, size, withCDN) } + async createContexts(options?: CreateContextsOptions): Promise { + return await StorageContext.createContexts(this._synapse, this._warmStorageService, { + ...options, + withCDN: options?.withCDN ?? this._withCDN, + withIpni: options?.withIpni ?? this._withIpni, + dev: options?.dev ?? this._dev, + }) + } + /** * Create a new storage context with specified options */ @@ -252,7 +262,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 11b302133..27c73ae4b 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 32ee304da..e1ebdc4c4 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/mocks/jsonrpc/index.ts b/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts index 7ddc057f5..6f28ecc6f 100644 --- a/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts +++ b/packages/synapse-sdk/src/test/mocks/jsonrpc/index.ts @@ -1,3 +1,4 @@ +import { AbiCoder } from 'ethers' import { HttpResponse, http } from 'msw' import type { RequiredDeep } from 'type-fest' import { @@ -45,6 +46,36 @@ export const ADDRESSES = { }, } +function jsonrpcHandler(item: RpcRequest, options?: JSONRPCOptions): RpcResponse { + const { id } = item + try { + return { + jsonrpc: '2.0', + result: handler(item, options ?? {}), + id: id ?? 1, + } + } catch (error) { + if (options?.debug) { + console.error(error) + } + return { + jsonrpc: '2.0', + error: { + code: 11, + message: + error instanceof Error + ? `message execution failed (exit=[33], revert reason=[message failed with backtrace:\n00: f0176092 (method 3844450837) -- contract reverted at 75 (33)\n01: f0176092 (method 6) -- contract reverted at 15151 (33)\n (RetCode=33)], vm error=[Error(${error.message})])` + : 'Unknown error', + data: + error instanceof Error + ? `0x08c379a0${AbiCoder.defaultAbiCoder().encode(['string'], [error.message]).slice(2)}` + : '0x', + }, + id: id ?? 1, + } + } +} + /** * Mock JSONRPC server for testing */ @@ -52,40 +83,15 @@ export function JSONRPC(options?: JSONRPCOptions) { return http.post, RpcRequest | RpcRequest[], RpcResponse | RpcResponse[]>( 'https://api.calibration.node.glif.io/rpc/v1', async ({ request }) => { - try { - const body = await request.json() - if (Array.isArray(body)) { - const results: RpcResponse[] = [] - for (const item of body) { - const { id } = item - const result = handler(item, options ?? {}) - results.push({ - jsonrpc: '2.0', - result: result, - id: id ?? 1, - }) - } - return HttpResponse.json(results) - } else { - const { id } = body - return HttpResponse.json({ - jsonrpc: '2.0', - result: handler(body, options ?? {}), - id: id ?? 1, - }) - } - } catch (error) { - if (options?.debug) { - console.error(error) + const body = await request.json() + if (Array.isArray(body)) { + const results: RpcResponse[] = [] + for (const item of body) { + results.push(jsonrpcHandler(item, options)) } - return HttpResponse.json({ - jsonrpc: '2.0', - error: { - code: -32000, - message: error instanceof Error ? error.message : 'Unknown error', - }, - id: 1, - }) + return HttpResponse.json(results) + } else { + return HttpResponse.json(jsonrpcHandler(body, options)) } } ) @@ -245,7 +251,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 +281,7 @@ export const presets = { pdpEndEpoch: 0n, providerId: 1n, cdnEndEpoch: 0n, + dataSetId: 1n, }, ], ], @@ -293,6 +300,7 @@ export const presets = { pdpEndEpoch: 0n, providerId: 1n, cdnEndEpoch: 0n, + dataSetId: 1n, }, ], getApprovedProviders: () => [[1n, 2n]], @@ -329,7 +337,7 @@ export const presets = { return [true, 'bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi'] return [false, ''] // key not found }, - clientDataSetIDs: () => { + clientDataSetIds: () => { return [BigInt(0)] }, }, @@ -341,12 +349,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 +379,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/service-registry.ts b/packages/synapse-sdk/src/test/mocks/jsonrpc/service-registry.ts index 6c7801a7f..dc4317b46 100644 --- a/packages/synapse-sdk/src/test/mocks/jsonrpc/service-registry.ts +++ b/packages/synapse-sdk/src/test/mocks/jsonrpc/service-registry.ts @@ -1,6 +1,7 @@ /** biome-ignore-all lint/style/noNonNullAssertion: testing */ import type { ExtractAbiFunction } from 'abitype' +import { assert } from 'chai' import { decodeFunctionData, encodeAbiParameters, type Hex } from 'viem' import { CONTRACT_ABIS } from '../../../utils/constants.ts' import type { AbiToType, JSONRPCOptions } from './types.ts' @@ -28,6 +29,87 @@ export interface ServiceRegistryOptions { getProvider?: (args: AbiToType) => AbiToType } +export type ServiceProviderInfoView = AbiToType[0] +export type PDPServiceInfoView = AbiToType + +const EMPTY_PROVIDER: ServiceProviderInfoView = { + providerId: 0n, + info: { + serviceProvider: '0x0000000000000000000000000000000000000000', + payee: '0x0000000000000000000000000000000000000000', + name: '', + description: '', + isActive: false, + }, +} + +const EMPTY_PDP_SERVICE: PDPServiceInfoView = [ + { + serviceURL: '', + minPieceSizeInBytes: 0n, + maxPieceSizeInBytes: 0n, + ipniPiece: false, + ipniIpfs: false, + storagePricePerTibPerMonth: 0n, + minProvingPeriodInEpochs: 0n, + location: '', + paymentTokenAddress: '0x0000000000000000000000000000000000000000', + }, + [], // capabilityKeys + false, // isActive +] + +export function mockServiceProviderRegistry( + providers: ServiceProviderInfoView[], + services?: (PDPServiceInfoView | null)[] +): ServiceRegistryOptions { + assert.isAtMost(services?.length ?? 0, providers.length) + return { + getProvider: ([providerId]) => { + if (providerId < 0n || providerId > providers.length) { + throw new Error('Provider does not exist') + } + for (const provider of providers) { + if (providerId === provider.providerId) { + return [provider] + } + } + throw new Error('Provider not found') + }, + getPDPService: ([providerId]) => { + if (!services) { + return EMPTY_PDP_SERVICE + } + for (let i = 0; i < services.length; i++) { + if (providers[i].providerId === providerId) { + const service = services[i] + if (service == null) { + return EMPTY_PDP_SERVICE + } + return service + } + } + return EMPTY_PDP_SERVICE + }, + getProviderByAddress: ([address]) => { + for (const provider of providers) { + if (address === provider.info.serviceProvider) { + return [provider] + } + } + return [EMPTY_PROVIDER] + }, + getProviderIdByAddress: ([address]) => { + for (const provider of providers) { + if (address === provider.info.serviceProvider) { + return [provider.providerId] + } + } + return [0n] + }, + } +} + /** * Handle service provider registry calls */ 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 4cf8b0acf..dc59e95f9 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 797e4106e..41f22353b 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/rand.test.ts b/packages/synapse-sdk/src/test/rand.test.ts new file mode 100644 index 000000000..fcb44380f --- /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 650e2c4bb..dd65b7aa5 100644 --- a/packages/synapse-sdk/src/test/retriever-chain.test.ts +++ b/packages/synapse-sdk/src/test/retriever-chain.test.ts @@ -87,7 +87,6 @@ const mockDataSet: EnhancedDataSetInfo = { clientDataSetId: 1, 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: {}, } 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 df461ed57..c3664fb74 100644 --- a/packages/synapse-sdk/src/test/sp-registry-service.test.ts +++ b/packages/synapse-sdk/src/test/sp-registry-service.test.ts @@ -26,47 +26,42 @@ 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, - } - } - throw new Error('Provider not found') - }, - getProviderProducts: async (id: number) => { - if (id === 1) { - return [ - { - productType: 0, // PDP + providerId: 1, + info: { + serviceProvider: mockProviderAddress, + payee: mockProviderAddress, + name: 'Test Provider', + description: 'A test storage provider', isActive: true, - capabilityKeys: [], - productData: '0x', // Encoded PDP offering }, - ] + } } - return [] + throw new Error('Provider not found') }, providerHasProduct: async (id: number, productType: number) => { return id === 1 && productType === 0 @@ -74,7 +69,7 @@ describe('SPRegistryService', () => { getPDPService: async (id: number) => { if (id === 1) { return { - offering: { + pdpOffering: { serviceURL: 'https://provider.example.com', minPieceSizeInBytes: SIZE_CONSTANTS.KiB, maxPieceSizeInBytes: SIZE_CONSTANTS.GiB, @@ -406,7 +401,20 @@ describe('SPRegistryService', () => { // Override to return provider without products ;(service as any)._getRegistryContract = () => ({ ...createMockContract(), - getProviderProducts: async () => [], + getPDPService: async () => ({ + pdpOffering: { + serviceURL: '', + minPieceSizeInBytes: 0, + maxPieceSizeInBytes: 0, + ipniPiece: false, + ipniIpfs: false, + minProvingPeriodInEpochs: 0, + storagePricePerTibPerMonth: 0, + location: '', + }, + capabilityKeys: [], + isActive: false, + }), }) const provider = await service.getProvider(1) diff --git a/packages/synapse-sdk/src/test/storage.test.ts b/packages/synapse-sdk/src/test/storage.test.ts index 0fa1cd9fd..7b8ea3d77 100644 --- a/packages/synapse-sdk/src/test/storage.test.ts +++ b/packages/synapse-sdk/src/test/storage.test.ts @@ -5,6 +5,7 @@ import { StorageContext } from '../storage/context.ts' import type { Synapse } from '../synapse.ts' import type { PieceCID, ProviderInfo, UploadResult } from '../types.ts' import { SIZE_CONSTANTS } from '../utils/constants.ts' +import { ADDRESSES } from './mocks/jsonrpc/index.ts' import { createMockProviderInfo, createSimpleProvider, setupProviderRegistryMocks } from './test-utils.ts' // Create a mock Ethereum provider that doesn't try to connect @@ -143,7 +144,7 @@ function createMockWarmStorageService(providers: ProviderInfo[], dataSets: any[] return provider?.id ?? 0 }, getApprovedProvider: async (id: number) => providers.find((p) => p.id === id) ?? null, - getServiceProviderRegistryAddress: () => '0x0000000000000000000000000000000000000001', + getServiceProviderRegistryAddress: () => ADDRESSES.calibration.spRegistry, getApprovedProviderIds: async () => providers.map((p) => p.id), isProviderIdApproved: async (id: number) => providers.some((p) => p.id === id), getDataSetMetadata: async (dataSetId: number) => { diff --git a/packages/synapse-sdk/src/test/synapse.test.ts b/packages/synapse-sdk/src/test/synapse.test.ts index 2d06cb434..a5bc4a85f 100644 --- a/packages/synapse-sdk/src/test/synapse.test.ts +++ b/packages/synapse-sdk/src/test/synapse.test.ts @@ -15,6 +15,8 @@ import { PDP_PERMISSIONS } from '../session/key.ts' import { Synapse } from '../synapse.ts' import { makeDataSetCreatedLog } from './mocks/events.ts' import { ADDRESSES, JSONRPC, PRIVATE_KEYS, presets } from './mocks/jsonrpc/index.ts' +import type { PDPServiceInfoView, ServiceProviderInfoView } from './mocks/jsonrpc/service-registry.ts' +import { mockServiceProviderRegistry } from './mocks/jsonrpc/service-registry.ts' import { createDataSetHandler, dataSetCreationStatusHandler, type PDPMockOptions } from './mocks/pdp/handlers.ts' import { PING } from './mocks/ping.ts' @@ -327,10 +329,7 @@ describe('Synapse', () => { }, payments: { ...presets.basic.payments, - operatorApprovals: (args) => { - const token = args[0] - const client = args[1] - const operator = args[2] + operatorApprovals: ([token, client, operator]) => { assert.equal(token, ADDRESSES.calibration.usdfcToken) assert.equal(client, signerAddress) assert.equal(operator, ADDRESSES.calibration.warmStorage) @@ -343,9 +342,7 @@ describe('Synapse', () => { BigInt(28800), // maxLockupPeriod ] }, - accounts: (args) => { - const token = args[0] - const user = args[1] + accounts: ([token, user]) => { assert.equal(user, signerAddress) assert.equal(token, ADDRESSES.calibration.usdfcToken) return [BigInt(127001 * 635000000), BigInt(0), BigInt(0), BigInt(0)] @@ -461,12 +458,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 +706,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, + }, }, ] }, @@ -761,4 +765,206 @@ describe('Synapse', () => { } }) }) + + describe('createContexts', () => { + let synapse: Synapse + const mockProviders: ServiceProviderInfoView[] = [ + { + providerId: 1n, + info: { + serviceProvider: ADDRESSES.serviceProvider1, + payee: ADDRESSES.serviceProvider1, + name: 'serviceProvider1', + description: 'mockProviders[0]', + isActive: true, + }, + }, + { + providerId: 2n, + info: { + serviceProvider: ADDRESSES.serviceProvider2, + payee: ADDRESSES.serviceProvider2, + name: 'serviceProvider2', + description: 'mockProviders[1]', + isActive: true, + }, + }, + ] + const mockPDPProducts: PDPServiceInfoView[] = [ + [ + { + serviceURL: 'http://serviceProvider1.com', + minPieceSizeInBytes: 0n, + maxPieceSizeInBytes: 1n << 32n, + ipniPiece: false, + ipniIpfs: false, + storagePricePerTibPerMonth: 1000n, + minProvingPeriodInEpochs: 3n, + location: 'narnia', + paymentTokenAddress: ADDRESSES.calibration.usdfcToken, + }, + [], // capabilityKeys + true, // isActive + ], + [ + { + serviceURL: 'http://serviceProvider2.org', + minPieceSizeInBytes: 0n, + maxPieceSizeInBytes: 1n << 32n, + ipniPiece: false, + ipniIpfs: false, + storagePricePerTibPerMonth: 1000n, + minProvingPeriodInEpochs: 3n, + location: 'krypton', + paymentTokenAddress: ADDRESSES.calibration.usdfcToken, + }, + [], // capabilityKeys + true, // isActive + ], + ] + + const DATA_SET_ID = 7 + + const FAKE_TX_HASH = '0x3816d82cb7a6f5cde23f4d63c0763050d13c6b6dc659d0a7e6eba80b0ec76a18' + + const FAKE_TX = { + hash: FAKE_TX_HASH, + from: ADDRESSES.serviceProvider1, + gas: '0x5208', + value: '0x0', + nonce: '0x444', + input: '0x', + v: '0x01', + r: '0x4e2eef88cc6f2dc311aa3b1c8729b6485bd606960e6ae01522298278932c333a', + s: '0x5d0e08d8ecd6ed8034aa956ff593de9dc1d392e73909ef0c0f828918b58327c9', + } + + const FAKE_RECEIPT = { + ...FAKE_TX, + transactionHash: FAKE_TX_HASH, + transactionIndex: '0x10', + blockHash: '0xb91b7314248aaae06f080ad427dbae78b8c5daf72b2446cf843739aef80c6417', + status: '0x1', + blockNumber: '0x127001', + cumulativeGasUsed: '0x52080', + gasUsed: '0x5208', + logs: [makeDataSetCreatedLog(DATA_SET_ID, 1)], + } + + beforeEach(async () => { + server.use( + JSONRPC({ + ...presets.basic, + serviceRegistry: mockServiceProviderRegistry(mockProviders, mockPDPProducts), + eth_getTransactionByHash: (params) => { + const hash = params[0] + assert.equal(hash, FAKE_TX_HASH) + return FAKE_TX + }, + eth_getTransactionReceipt: (params) => { + const hash = params[0] + assert.equal(hash, FAKE_TX_HASH) + return FAKE_RECEIPT + }, + }) + ) + synapse = await Synapse.create({ signer }) + for (const [mockProduct] of mockPDPProducts) { + const pdpOptions: PDPMockOptions = { + baseUrl: mockProduct.serviceURL, + } + server.use(createDataSetHandler(FAKE_TX_HASH, pdpOptions)) + server.use( + dataSetCreationStatusHandler( + FAKE_TX_HASH, + { + ok: true, + dataSetId: DATA_SET_ID, + createMessageHash: '', + dataSetCreated: true, + service: '', + txStatus: '', + }, + pdpOptions + ) + ) + } + }) + + it('selects specified providerIds', async () => { + const contexts = await synapse.storage.createContexts({ + providerIds: [mockProviders[0].providerId, mockProviders[1].providerId].map(Number), + }) + assert.equal(contexts.length, 2) + assert.equal(BigInt(contexts[0].provider.id), mockProviders[0].providerId) + assert.equal(BigInt(contexts[1].provider.id), mockProviders[1].providerId) + // created new data sets; got the mocked data set id + assert.equal((contexts[0] as any)._dataSetId, DATA_SET_ID) + assert.equal((contexts[1] as any)._dataSetId, DATA_SET_ID) + }) + + it('fails when provided an invalid providerId', async () => { + try { + await synapse.storage.createContexts({ + providerIds: [3, 4], + }) + assert.fail('Expected createContexts to fail for invalid specified providerIds') + } catch (error: any) { + assert.include(error.message, 'Provider does not exist') + } + }) + + it('selects providers specified by address', async () => { + const contexts = await synapse.storage.createContexts({ + providerAddresses: [mockProviders[1].info.serviceProvider, mockProviders[0].info.serviceProvider], + }) + assert.equal(contexts.length, 2) + assert.equal(BigInt(contexts[1].provider.id), mockProviders[0].providerId) + assert.equal(BigInt(contexts[0].provider.id), mockProviders[1].providerId) + // created new data sets; got the mocked data set id + assert.equal((contexts[1] as any)._dataSetId, DATA_SET_ID) + assert.equal((contexts[0] as any)._dataSetId, DATA_SET_ID) + }) + + it('fails when provided an invalid provider address', async () => { + try { + await synapse.storage.createContexts({ + providerAddresses: [ADDRESSES.client1], + }) + assert.fail('Expected createContexts to fail for invalid specified provider address') + } catch (error: any) { + assert.equal( + error?.message, + `StorageContext resolveByProviderAddress failed: Provider ${ADDRESSES.client1} is not currently approved` + ) + } + }) + + it('selects providers specified by data set id', async () => { + const contexts = await synapse.storage.createContexts({ + count: 1, + dataSetIds: [1], + }) + assert.equal(contexts.length, 1) + assert.equal(contexts[0].provider.id, 1) + assert.equal((contexts[0] as any)._dataSetId, 1n) + }) + + it('fails when provided an invalid data set id', async () => { + for (const dataSetId of [0, 2]) { + try { + await synapse.storage.createContexts({ + count: 1, + dataSetIds: [dataSetId], + }) + assert.fail('Expected createContexts to fail for invalid specified data set id') + } catch (error: any) { + assert.equal( + error?.message, + `StorageContext resolveByDataSetId failed: Data set ${dataSetId} not found, not owned by ${ADDRESSES.client1}, or not managed by the current WarmStorage contract` + ) + } + } + }) + }) }) diff --git a/packages/synapse-sdk/src/test/test-utils.ts b/packages/synapse-sdk/src/test/test-utils.ts index 7023e5248..0487ec42f 100644 --- a/packages/synapse-sdk/src/test/test-utils.ts +++ b/packages/synapse-sdk/src/test/test-utils.ts @@ -20,6 +20,7 @@ import type { ProviderInfo } from '../sp-registry/types.ts' import { CONTRACT_ABIS, CONTRACT_ADDRESSES, SIZE_CONSTANTS, TIME_CONSTANTS } from '../utils/constants.ts' import { ProviderResolver } from '../utils/provider-resolver.ts' import type { WarmStorageService } from '../warm-storage/index.ts' +import { ADDRESSES } from './mocks/jsonrpc/index.ts' /** * Addresses used by testing @@ -141,8 +142,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 @@ -151,7 +152,7 @@ export function createMockProvider(chainId: number = 314159): ethers.Provider { } // serviceProviderRegistry() - function selector: 0x05f892ec if (data?.startsWith('0x05f892ec') === true) { - return ethers.AbiCoder.defaultAbiCoder().encode(['address'], ['0x0000000000000000000000000000000000000001']) + return ethers.AbiCoder.defaultAbiCoder().encode(['address'], [ADDRESSES.calibration.spRegistry]) } // sessionKeyRegistry() - function selector: 0x9f6aa572 if (data?.startsWith('0x9f6aa572') === true) { @@ -273,20 +274,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 +296,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 ]) @@ -458,7 +460,7 @@ export function createCustomMulticall3Mock( customAddresses?.usdfcToken ?? CONTRACT_ADDRESSES.USDFC.calibration, // usdfcToken customAddresses?.filCDN ?? '0x0000000000000000000000000000000000000000', // filCDN (not used) customAddresses?.viewContract ?? MOCK_ADDRESSES.WARM_STORAGE_VIEW, // viewContract - customAddresses?.spRegistry ?? '0x0000000000000000000000000000000000000001', // spRegistry + customAddresses?.spRegistry ?? ADDRESSES.calibration.spRegistry, // spRegistry customAddresses?.sessionKeyRegistry ?? MOCK_ADDRESSES.SESSION_KEY_REGISTRY, // sessionKeyRegistry ] @@ -627,13 +629,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 { @@ -645,18 +640,15 @@ export function setupProviderRegistryMocks( if (callData.startsWith('0xab2b3ae5')) { return { success: true, - returnData: ethers.AbiCoder.defaultAbiCoder().encode( - ['address'], - ['0x0000000000000000000000000000000000000001'] - ), + returnData: ethers.AbiCoder.defaultAbiCoder().encode(['address'], [ADDRESSES.calibration.spRegistry]), } } } // 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)]), @@ -666,26 +658,41 @@ export function setupProviderRegistryMocks( // Mock getProvider(uint256) calls to SPRegistry // Check if it's to the SPRegistry address - if (callData.startsWith('0x5c42d079') && target === '0x0000000000000000000000000000000000000001') { + if (callData.startsWith('0x5c42d079') && target === ADDRESSES.calibration.spRegistry) { const providerId = parseInt(callData.slice(10, 74), 16) 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 } } // Mock getPDPService(uint256) calls - if (callData.startsWith('0xc439fd57') && target === '0x0000000000000000000000000000000000000001') { + if (callData.startsWith('0xc439fd57') && target === ADDRESSES.calibration.spRegistry) { const providerId = parseInt(callData.slice(10, 74), 16) const provider = providers.find((p) => p.id === providerId) if (provider?.products?.PDP) { @@ -732,7 +739,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 +752,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]]] ) } @@ -806,47 +822,6 @@ export function setupProviderRegistryMocks( ) } - // Mock getProviderProducts(uint256) - returns products for provider - if (data?.startsWith('0xb5eb46e1')) { - const providerId = parseInt(data.slice(10, 74), 16) - const provider = providers.find((p) => p.id === providerId) - if (provider?.products?.PDP) { - const pdp = provider.products.PDP - - // Encode PDP product data (simplified for testing) - const encodedPDP = ethers.AbiCoder.defaultAbiCoder().encode( - ['string', 'uint256', 'uint256', 'bool', 'bool', 'uint256', 'uint256', 'string', 'address'], - [ - pdp.data.serviceURL, - pdp.data.minPieceSizeInBytes, - pdp.data.maxPieceSizeInBytes, - pdp.data.ipniPiece, - pdp.data.ipniIpfs, - pdp.data.storagePricePerTibPerMonth, - pdp.data.minProvingPeriodInEpochs, - pdp.data.location || '', - pdp.data.paymentTokenAddress, - ] - ) - - return ethers.AbiCoder.defaultAbiCoder().encode( - ['tuple(uint8,bool,bytes32[],bytes)[]'], - [ - [ - [ - 0, // productType: PDP - pdp.isActive, - pdp.capabilities ?? [], // capabilityKeys (empty for simplicity) - encodedPDP, - ], - ], - ] - ) - } - // Return empty products array - return ethers.AbiCoder.defaultAbiCoder().encode(['tuple(uint8,bool,bytes32[],bytes)[]'], [[]]) - } - // Mock decodePDPOffering(bytes) - decode PDP product data if (data?.startsWith('0xdeb0e462')) { // For simplicity, return a default PDP offering @@ -890,14 +865,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 5dfaf63c1..23de18022 100644 --- a/packages/synapse-sdk/src/test/warm-storage-service.test.ts +++ b/packages/synapse-sdk/src/test/warm-storage-service.test.ts @@ -97,7 +97,7 @@ describe('WarmStorageService', () => { clientDataSetId: 5, pdpEndEpoch: 0, providerId: 1, - cdnEndEpoch: 0, + dataSetId: BigInt(dataSetId), } // Use the Interface to encode the return data properly return viewInterface.encodeFunctionResult('getDataSet', [dataSetInfo]) @@ -133,7 +133,7 @@ describe('WarmStorageService', () => { clientDataSetId: 0, 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, ], ] @@ -347,7 +349,7 @@ describe('WarmStorageService', () => { clientDataSetId: 0, pdpEndEpoch: 0, providerId: 1, - cdnEndEpoch: 0, + dataSetId: 242n, } return viewInterface.encodeFunctionResult('getDataSet', [dataSetInfo]) } @@ -422,7 +424,7 @@ describe('WarmStorageService', () => { clientDataSetId: id === 242 ? 0 : 1, 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)]) @@ -511,7 +513,7 @@ describe('WarmStorageService', () => { clientDataSetId: 0, 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]) } @@ -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 diff --git a/packages/synapse-sdk/src/types.ts b/packages/synapse-sdk/src/types.ts index 3ee48741a..fd2398b1b 100644 --- a/packages/synapse-sdk/src/types.ts +++ b/packages/synapse-sdk/src/types.ts @@ -214,10 +214,10 @@ export interface DataSetInfo { 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 */ @@ -318,6 +320,42 @@ export interface StorageCreationCallbacks { }) => void } +export interface CreateContextsOptions { + /** Number of contexts to create (optional, defaults to 2) */ + count?: number + /** + * Specific provider IDs to use (if not using providerAddresses) + * Must be no longer than count + */ + providerIds?: number[] + /** + * Specific provider addresses to use (if not using providerIds) + * Must be no longer than count + */ + providerAddresses?: string[] + /** + * Specific data set IDs to use + * Cannot be used with provider options + * Must be no longer than count + */ + dataSetIds?: number[] + /** Whether to enable CDN services */ + withCDN?: boolean + withIpni?: boolean + dev?: boolean + /** + * Custom metadata for the data sets (key-value pairs) + * When smart-selecting data sets, this metadata will be used to match. + */ + metadata?: Record + /** Create new data sets, even if candidates exist */ + forceCreateDataSets?: boolean + /** Callbacks for creation process (will need to change to handle multiples) */ + callbacks?: StorageCreationCallbacks + /** Maximum number of uploads to process in a single batch (default: 32, minimum: 1) */ + uploadBatchSize?: number +} + /** * Options for creating or selecting a storage context * @@ -331,6 +369,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) */ @@ -549,8 +589,6 @@ export interface ProviderSelectionResult { provider: ProviderInfo /** Selected data set ID */ dataSetId: number - /** Whether this is a new data set that was created */ - isNewDataSet?: boolean /** Whether this is an existing data set */ isExisting?: boolean /** Data set metadata */ diff --git a/packages/synapse-sdk/src/utils/constants.ts b/packages/synapse-sdk/src/utils/constants.ts index 70aa0ac18..9996956ba 100644 --- a/packages/synapse-sdk/src/utils/constants.ts +++ b/packages/synapse-sdk/src/utils/constants.ts @@ -319,7 +319,7 @@ export const CONTRACT_ADDRESSES = { */ WARM_STORAGE: { mainnet: '0x81DFD9813aDd354f03704F31419b0c6268d46232', - calibration: '0x80617b65FD2EEa1D7fDe2B4F85977670690ed348', + calibration: '0x468342072e0dc86AFFBe15519bc5B1A1aa86e4dc', } as const satisfies Record, /** diff --git a/packages/synapse-sdk/src/utils/index.ts b/packages/synapse-sdk/src/utils/index.ts index 82f151d1c..b75b0c5d6 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 000000000..e682615ac --- /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 e15447574..ca2546864 100644 --- a/packages/synapse-sdk/src/warm-storage/service.ts +++ b/packages/synapse-sdk/src/warm-storage/service.ts @@ -114,7 +114,7 @@ export class WarmStorageService { pdpVerifier: string payments: string usdfcToken: string - filCDNBeneficiary: string + filBeamBeneficiary: string viewContract: string serviceProviderRegistry: string sessionKeyRegistry: string @@ -130,7 +130,7 @@ export class WarmStorageService { pdpVerifier: string payments: string usdfcToken: string - filCDNBeneficiary: string + filBeamBeneficiary: string viewContract: string serviceProviderRegistry: string sessionKeyRegistry: string @@ -176,7 +176,7 @@ export class WarmStorageService { { target: warmStorageAddress, allowFailure: false, - callData: iface.encodeFunctionData('filCDNBeneficiaryAddress'), + callData: iface.encodeFunctionData('filBeamBeneficiaryAddress'), }, { target: warmStorageAddress, @@ -201,7 +201,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], @@ -306,7 +306,7 @@ export class WarmStorageService { clientDataSetId: Number(ds.clientDataSetId), pdpEndEpoch: Number(ds.pdpEndEpoch), providerId: Number(ds.providerId), - cdnEndEpoch: Number(ds.cdnEndEpoch), + dataSetId, } } @@ -332,7 +332,6 @@ export class WarmStorageService { clientDataSetId: Number(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)}`) @@ -447,27 +446,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 +1010,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 +1026,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)) } diff --git a/packages/synapse-sdk/wagmi.config.ts b/packages/synapse-sdk/wagmi.config.ts index c2e151687..634b1b905 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 = 'c041cf494e104a6492c8816914e44be62eff8ea7' +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 = [