costs

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 11, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package costs provides cost calculation for storage operations.

It computes upload costs based on service pricing, data set sizes, effective rates, lockup requirements, and CDN options. The calculation matches on-chain Solidity integer division for accuracy.

Entry points

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. Monthly figures in this package are derived by multiplying per-epoch rates by github.com/strahe/synapse-go/chain.EpochsPerMonth.

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 %).

CDN fee — the optional egress fee charged when a dataset opts in to FilBeam CDN delivery. Applied on top of the base PDP rate and split between cache-hit and cache-miss rails.

Sybil fee — a small flat USDFC amount that warmstorage locks on dataset creation to deter spam. Added to each upload cost estimate.

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)
}

Index

Examples

Constants

View Source
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

View Source
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.

View Source
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

func CDNFixedLockupValue() *big.Int

CDNFixedLockupValue returns the fixed lockup amount for new CDN-enabled datasets (1.0 USDFC). The caller owns the returned value and may modify it freely.

func CalculateDepositNeeded

func CalculateDepositNeeded(
	additionalLockup *big.Int,
	rateDelta *big.Int,
	currentLockupRate *big.Int,
	debt *big.Int,
	availableFunds *big.Int,
	runwayEpochs int64,
	bufferEpochs int64,
	isNewDataSet bool,
) *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 arguments 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
	CurrentEpoch       *big.Int
}

AccountSummary is the snapshot of an account's payment state.

type AdditionalLockup

type AdditionalLockup struct {
	RateDelta      *big.Int // marginal rate per epoch added by this upload
	RateLockup     *big.Int // RateDelta * lockupPeriod
	CDNFixedLockup *big.Int // 1.0 USDFC for new CDN datasets, 0 otherwise
	SybilFee       *big.Int // anti-sybil fee for new datasets, 0 otherwise
	TotalLockup    *big.Int // sum of all components
}

AdditionalLockup is the incremental lockup required when adding data to a dataset. TotalLockup = RateLockup + CDNFixedLockup + SybilFee.

func CalculateAdditionalLockupRequired

func CalculateAdditionalLockupRequired(
	dataSizeBytes *big.Int,
	currentDataSetSizeBytes *big.Int,
	pricing *warmstorage.ServicePrice,
	lockupPeriod int64,
	usdfcSybilFee *big.Int,
	isNewDataSet bool,
	enableCDN bool,
) AdditionalLockup

CalculateAdditionalLockupRequired returns the incremental lockup needed to store uploadSizeBytes into a dataset that currently holds currentDataSetSizeBytes. usdfcSybilFee may be nil (treated as zero).

type ContractCaller

type ContractCaller interface {
	CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error)
}

ContractCaller is the subset of ethereum.ContractCaller needed by Service.

type EffectiveRate

type EffectiveRate struct {
	RatePerEpoch *big.Int
	RatePerMonth *big.Int
}

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.

func CalculateEffectiveRate

func CalculateEffectiveRate(
	sizeBytes *big.Int,
	pricePerTiBPerMonth *big.Int,
	minMonthlyRate *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 pricePerTiBPerMonth or minMonthlyRate 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 RatePerEpoch * EpochsPerMonth.
	RatePerMonth *big.Int
	// DepositNeeded is the single USDFC deposit covering all contexts.
	DepositNeeded *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 Sybil fee and optional CDN fixed
	// lockup). When false, CurrentDataSetSizeBytes is consulted so the
	// marginal rate is computed above the existing floor.
	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 floor-price rate is used.
	CurrentDataSetSizeBytes *big.Int

	// WithCDN toggles CDN fixed lockup for this target. Only meaningful
	// when IsNewDataSet is true — CDN lockup is only charged on creation.
	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.
	Chain chain.Chain

	// WarmStorage reads on-chain service pricing. Required.
	WarmStorage WarmStorageReader

	// Payments reads account and allowance state. Required.
	Payments PaymentsReader

	// Caller issues eth_call against the configured chain. 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 New

func New(opts Options) (*Service, error)

New constructs a Service using addresses from opts.Chain.Addresses(). WarmStorage, Payments and Caller must be non-nil.

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 (s *Service) GetAccountSummary(ctx context.Context, owner common.Address) (*AccountSummary, error)

GetAccountSummary returns a payment health snapshot for the given owner.

Deprecated: Use payments.Service.AccountSummary for payment account state. This method is kept for compatibility.

func (*Service) GetServicePrice

func (s *Service) GetServicePrice(ctx context.Context) (*warmstorage.ServicePrice, error)

GetServicePrice delegates to the warmstorage service.

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_FIXED_LOCKUP (1 USDFC) for a new dataset.
	EnableCDN bool
	// IsNewDataSet must be true when creating a fresh dataset (affects sybil fee and CDN lockup).
	IsNewDataSet bool
	// CurrentDataSetSizeBytes is the existing payload in the dataset (0 for new datasets).
	CurrentDataSetSizeBytes *big.Int
}

UploadCostOptions customises the GetUploadCosts calculation.

type UploadCosts

type UploadCosts struct {
	Rate                 EffectiveRate
	Lockup               AdditionalLockup
	DepositNeeded        *big.Int
	NeedsFWSSMaxApproval bool
	Ready                bool
}

UploadCosts is the result of GetUploadCosts.

type WarmStorageReader

type WarmStorageReader interface {
	GetServicePrice(ctx context.Context) (*warmstorage.ServicePrice, error)
}

WarmStorageReader is the subset of warmstorage.Service used by costs.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL