Documentation
¶
Overview ¶
Package costs provides cost calculation for storage operations.
It computes upload costs from the warmstorage PriceList, data set sizes, one-time operation fees, lockup requirements, and CDN options. The calculation matches on-chain Solidity integer division for accuracy.
Entry points ¶
- Service.GetUploadCosts — single-dataset upload cost.
- Service.CalculateMultiContextCosts — aggregated cost across multiple upload contexts (one new + N existing data sets); used by the storage manager's Prepare flow.
Payment account summary moved to `payments.Service.AccountSummary`. The older Service.GetAccountSummary method remains for compatibility.
Glossary ¶
Epoch — Filecoin block interval (30 seconds on mainnet and calibration). All on-chain rates and durations are denominated in epochs; 120 epochs equal one hour, ~86 400 equal one month. On-chain lockup rates are per-epoch; effective monthly rates preserve monthly pricing precision for display and comparison.
Basis points (bps) — one hundredth of one percent (1 bps = 0.01 %). Commission rates returned by warmstorage are expressed in basis points out of 10 000 (e.g. 500 bps = 5 %).
Fees — one-time operation charges such as dataset creation and add-pieces submission fees. Add-pieces fees are counted per PDP batch.
Lifecycle reserve — the flat lockup required when creating a dataset. It is separate from one-time operation fees.
Lockup — funds reserved on the FilecoinPay contract to guarantee a stream of payments. `LockupRatePerEpoch` is the per-epoch drain rate; `FundedUntilEpoch` is the epoch at which existing funds are exhausted at that rate.
Stability ¶
0.x phase: public API may change between minor releases.
Example ¶
Example demonstrates fetching an account summary via costs.Service. In practice a Service is obtained from synapse.Client.Costs.
package main
import (
"context"
"fmt"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/strahe/synapse-go/costs"
)
func main() {
var svc *costs.Service // obtained from synapse.Client.Costs()
ctx := context.Background()
owner := common.HexToAddress("0x...")
summary, err := svc.GetAccountSummary(ctx, owner) //nolint:staticcheck // compatibility example for legacy costs callers
if err != nil {
log.Fatal(err)
}
fmt.Println(summary.AvailableFunds)
}
Output:
Index ¶
- Constants
- Variables
- func CDNFixedLockupValue() *big.Intdeprecated
- func CalculateDepositNeeded(calc DepositCalculation) *big.Int
- type AccountSummary
- type AdditionalLockup
- type ContractCaller
- type DepositCalculation
- type EffectiveRate
- type MultiContextCosts
- type MultiContextRef
- type Options
- type PaymentsReader
- type Service
- func (s *Service) CalculateMultiContextCosts(ctx context.Context, payer common.Address, dataSizeBytes *big.Int, ...) (*MultiContextCosts, error)
- func (s *Service) GetAccountSummary(ctx context.Context, owner common.Address) (*AccountSummary, error)deprecated
- func (s *Service) GetPriceList(ctx context.Context) (*warmstorage.PriceList, error)
- func (s *Service) GetServicePrice(ctx context.Context) (*warmstorage.ServicePrice, error)deprecated
- func (s *Service) GetUploadCosts(ctx context.Context, payer common.Address, dataSizeBytes *big.Int, ...) (*UploadCosts, error)
- type UploadCostOptions
- type UploadCosts
- type UploadFees
- type WarmStorageReader
Examples ¶
Constants ¶
const ( // DefaultExtraRunwayEpochs adds no runway above the lockup period. DefaultExtraRunwayEpochs int64 = 0 // DefaultBufferEpochs is a 5-epoch deposit cushion for transaction execution latency. DefaultBufferEpochs int64 = 5 // DefaultLockupPeriod is the standard lockup horizon (30 days in epochs). DefaultLockupPeriod int64 = chain.EpochsPerMonth )
Variables ¶
var ErrClosed = lifecycle.ErrClosed
ErrClosed is returned when a method is called after the owning Client has been closed. It aliases the shared closed-client sentinel.
var ErrUninitialized = errors.New("costs: service not initialized; use costs.New")
ErrUninitialized is returned when a method is invoked on a zero-value Service (one that was not constructed via New).
Functions ¶
func CDNFixedLockupValue
deprecated
func CalculateDepositNeeded ¶
func CalculateDepositNeeded(calc DepositCalculation) *big.Int
CalculateDepositNeeded computes the USDFC deposit required to cover lockup, runway, and buffer.
Buffer is skipped when currentLockupRate is zero and isNewDataSet is true: the deposit lands before the payment rail is created so the contract cannot yet drain it.
Nil *big.Int fields are treated as zero. Negative epoch counts are clamped to zero.
Types ¶
type AccountSummary ¶
type AccountSummary struct {
Funds *big.Int
AvailableFunds *big.Int
Debt *big.Int
LockupRatePerEpoch *big.Int
LockupRatePerMonth *big.Int
FundedUntilEpoch *big.Int
RunwayInEpochs *big.Int
GrossCoverageInEpochs *big.Int
CurrentEpoch *big.Int
}
AccountSummary is the snapshot of an account's payment state.
type AdditionalLockup ¶
type AdditionalLockup struct {
RateDeltaPerEpoch *big.Int
StreamingLockup *big.Int
LifecycleLockup *big.Int
CDNLockup *big.Int
CacheMissLockup *big.Int
Total *big.Int
// Deprecated: Use RateDeltaPerEpoch.
RateDelta *big.Int
// Deprecated: Use StreamingLockup.
RateLockup *big.Int
// Deprecated: Use CDNLockup and CacheMissLockup.
CDNFixedLockup *big.Int
// Deprecated: Use LifecycleLockup.
SybilFee *big.Int
// Deprecated: Use Total.
TotalLockup *big.Int
}
AdditionalLockup is the incremental lockup required when adding data to a dataset.
func CalculateAdditionalLockupRequired ¶
func CalculateAdditionalLockupRequired( dataSizeBytes *big.Int, currentDataSetSizeBytes *big.Int, priceList *warmstorage.PriceList, lockupPeriod *big.Int, isNewDataSet bool, enableCDN bool, ) AdditionalLockup
CalculateAdditionalLockupRequired returns the incremental lockup needed to store uploadSizeBytes into a dataset that currently holds currentDataSetSizeBytes. Nil dataSizeBytes, currentDataSetSizeBytes, and priceList use zero-value defaults.
type ContractCaller ¶
type ContractCaller interface {
CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
BlockNumber(ctx context.Context) (uint64, error)
}
ContractCaller is the chain reader accepted by Service. CallContract remains part of the public interface for compatibility; current cost calculations only use BlockNumber.
type DepositCalculation ¶ added in v0.3.1
type DepositCalculation struct {
// AdditionalLockup is the incremental lockup required by the upload.
AdditionalLockup *big.Int
// Fees are one-time operation fees required by the upload.
Fees *big.Int
// RateDelta is the incremental per-epoch payment rate added by the upload.
RateDelta *big.Int
// CurrentLockupRate is the account's existing per-epoch payment rate.
CurrentLockupRate *big.Int
// Debt is already-accrued payment debt that must be covered.
Debt *big.Int
// AvailableFunds is the account balance available after projected lockup.
AvailableFunds *big.Int
// RunwayInEpochs is the current account runway after projection.
RunwayInEpochs *big.Int
// ExtraRunwayEpochs is extra epoch runway on top of the required lockup.
ExtraRunwayEpochs int64
// BufferEpochs is the deposit buffer for execution latency.
// Zero means no buffer for direct calculations; service options apply their
// own default before calling CalculateDepositNeeded.
BufferEpochs int64
// IsNewDataSet is true when creating a fresh dataset.
IsNewDataSet bool
}
DepositCalculation is the input to CalculateDepositNeeded.
type EffectiveRate ¶
EffectiveRate is the per-epoch and per-month storage rate for a given data size. RatePerEpoch uses integer division to match on-chain Solidity truncation. RatePerMonth preserves monthly pricing precision for display and comparison.
func CalculateEffectiveRate ¶
func CalculateEffectiveRate( sizeBytes *big.Int, pricePerTiBPerMonth *big.Int, datasetFeePerMonth *big.Int, epochsPerMonth int64, ) EffectiveRate
CalculateEffectiveRate computes the storage rate for the given total data size. Integer division is used to match on-chain Solidity truncation. If epochsPerMonth is zero or negative, chain.EpochsPerMonth is used as a safe default. Nil sizeBytes, pricePerTiBPerMonth, or datasetFeePerMonth are treated as zero.
type MultiContextCosts ¶
type MultiContextCosts struct {
// RatePerEpoch is the sum of per-context effective rates (post-upload).
RatePerEpoch *big.Int
// RatePerMonth is the sum of per-context monthly effective rates.
RatePerMonth *big.Int
// Fees is the aggregate one-time fee breakdown.
Fees UploadFees
// Lockup is the aggregate lockup breakdown.
Lockup AdditionalLockup
// DepositNeeded is the single USDFC deposit covering all contexts.
DepositNeeded *big.Int
// RequiredLockupPeriod is the max lockup period required for FWSS
// approval, sourced from the price list.
RequiredLockupPeriod *big.Int
// NeedsFWSSMaxApproval is true when the FWSS operator does not yet
// hold max approval for the payer.
NeedsFWSSMaxApproval bool
// Ready is true when DepositNeeded is zero and FWSS approval is set.
Ready bool
}
MultiContextCosts is the aggregate cost view across multiple upload targets: a single DepositNeeded / NeedsFWSSMaxApproval / Ready, plus summed RatePerEpoch / RatePerMonth covering all refs.
type MultiContextRef ¶
type MultiContextRef struct {
// IsNewDataSet is true when the target will create a new data set
// on this provider (contributes lifecycle and optional CDN/cache-miss
// lockup). When false, CurrentDataSetSizeBytes is consulted so the
// marginal rate is computed above the existing size.
IsNewDataSet bool
// CurrentDataSetSizeBytes is the current on-chain size of the
// existing data set (zero or nil when IsNewDataSet is true). When
// unknown, pass nil and the marginal rate is computed from zero size.
CurrentDataSetSizeBytes *big.Int
// WithCDN toggles CDN and cache-miss lockup for this target. Only
// meaningful when IsNewDataSet is true.
WithCDN bool
}
MultiContextRef describes one upload target for Service.CalculateMultiContextCosts. Each ref yields its own lockup contribution; account-level debt, runway and buffer are computed once across the aggregate.
type Options ¶
type Options struct {
// Chain selects the network whose contract addresses are used.
// Zero value is chain.Mainnet. Explicit addresses below override the
// chain registry for callers that resolve current contracts dynamically.
Chain chain.Chain
// USDFCTokenAddress is the payment token used for account and approval
// reads. Zero falls back to Chain.Addresses().USDFC.
USDFCTokenAddress common.Address
// WarmStorageAddress is the FWSS operator used for approval reads. Zero
// falls back to Chain.Addresses().FWSS.
WarmStorageAddress common.Address
// WarmStorage reads on-chain service pricing. Required.
WarmStorage WarmStorageReader
// Payments reads account and allowance state. Required.
Payments PaymentsReader
// Caller provides chain reads for cost calculations. Required.
Caller ContractCaller
// Logger is the structured logger. If nil, logging is silent.
Logger *slog.Logger
// Lifecycle, when non-nil, ties this Service to the owning Client's
// close state. After the Lifecycle is closed, every method returns
// ErrClosed. Nil is allowed for standalone use.
Lifecycle *lifecycle.Lifecycle
}
Options configures a Service.
type PaymentsReader ¶
type PaymentsReader interface {
AccountInfo(ctx context.Context, token, owner common.Address) (*payments.AccountState, error)
ServiceApproval(ctx context.Context, token, client, operator common.Address) (*payments.OperatorApproval, error)
}
PaymentsReader is the subset of payments.Service used by costs.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service computes upload costs and account summaries for the FWSS ecosystem. All methods are safe for concurrent use.
func (*Service) CalculateMultiContextCosts ¶
func (s *Service) CalculateMultiContextCosts( ctx context.Context, payer common.Address, dataSizeBytes *big.Int, refs []MultiContextRef, opts *UploadCostOptions, ) (*MultiContextCosts, error)
CalculateMultiContextCosts aggregates upload costs across multiple prospective contexts for a single uploaded payload of dataSizeBytes.
Each ref contributes its own lockup; debt, runway and buffer are computed once from the payer's account state.
Default buffer/runway follow DefaultBufferEpochs / DefaultExtraRunwayEpochs when the corresponding opts field is zero.
func (*Service) GetAccountSummary
deprecated
func (*Service) GetPriceList ¶ added in v0.4.0
GetPriceList delegates to the warmstorage service.
func (*Service) GetServicePrice
deprecated
func (s *Service) GetServicePrice(ctx context.Context) (*warmstorage.ServicePrice, error)
GetServicePrice delegates to the warmstorage service.
Deprecated: Use GetPriceList.
func (*Service) GetUploadCosts ¶
func (s *Service) GetUploadCosts( ctx context.Context, payer common.Address, dataSizeBytes *big.Int, opts *UploadCostOptions, ) (*UploadCosts, error)
GetUploadCosts returns cost and deposit information for an upload.
payer is the client address. dataSizeBytes is the size of the new data. opts may be nil (defaults apply). opts.CurrentDataSetSizeBytes defaults to zero.
type UploadCostOptions ¶
type UploadCostOptions struct {
// ExtraRunwayEpochs is extra epoch runway on top of lockup. Defaults to DefaultExtraRunwayEpochs (0).
ExtraRunwayEpochs int64
// BufferEpochs is the deposit buffer for execution latency.
// Zero (the zero value) uses DefaultBufferEpochs (5); there is no way to
// request a zero-epoch buffer via this field.
BufferEpochs int64
// EnableCDN adds CDN and cache-miss lockup for a new dataset.
EnableCDN bool
// IsNewDataSet must be true when creating a fresh dataset.
IsNewDataSet bool
// CurrentDataSetSizeBytes is the existing payload in the dataset (0 for new datasets).
CurrentDataSetSizeBytes *big.Int
// PieceCount is the number of pieces added by this upload. Zero defaults
// to one piece.
PieceCount *big.Int
}
UploadCostOptions customises the GetUploadCosts calculation.
type UploadCosts ¶
type UploadCosts struct {
Rate EffectiveRate
Fees UploadFees
Lockup AdditionalLockup
DepositNeeded *big.Int
RequiredLockupPeriod *big.Int
NeedsFWSSMaxApproval bool
Ready bool
}
UploadCosts is the result of GetUploadCosts.
type UploadFees ¶ added in v0.4.0
UploadFees is the one-time fee breakdown for an upload.
func CalculateUploadFees ¶ added in v0.4.0
func CalculateUploadFees(priceList *warmstorage.PriceList, isNewDataSet bool, pieceCount *big.Int) UploadFees
CalculateUploadFees computes one-time upload fees from the price list.
type WarmStorageReader ¶
type WarmStorageReader interface {
GetPriceList(ctx context.Context) (*warmstorage.PriceList, error)
}
WarmStorageReader is the subset of warmstorage.Service used by costs.