Documentation
¶
Overview ¶
Package payments provides the payment management service for Filecoin Onchain Cloud.
It handles USDFC token operations including deposits, withdrawals, balance queries, approval management, and payment rail creation via the Filecoin Pay contract.
The root synapse Client wires payments together with the other write-capable services so transaction nonce allocation is coordinated for a shared signer. Standalone services create their own nonce coordinator when constructed with write dependencies.
Stability ¶
0.x phase: public API may change between minor releases.
Example ¶
Example shows reading an account balance via payments.Service. In practice a Service is obtained from synapse.Client.Payments.
package main
import (
"context"
"fmt"
"log"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/strahe/synapse-go/payments"
)
func main() {
var svc *payments.Service // obtained from synapse.Client.Payments()
ctx := context.Background()
usdfc := common.HexToAddress("0x...")
owner := common.HexToAddress("0x...")
bal, err := svc.Balance(ctx, usdfc, owner)
if err != nil {
log.Fatal(err)
}
fmt.Println(new(big.Int).Set(bal))
}
Output:
Index ¶
- Constants
- Variables
- type AccountState
- type Backend
- type ListOption
- type OperatorApproval
- type Options
- type PermitOption
- type RailListItem
- type RailPage
- type RailView
- type Service
- func (s *Service) Account() common.Address
- func (s *Service) AccountInfo(ctx context.Context, token, owner common.Address) (*AccountState, error)
- func (s *Service) Address() common.Address
- func (s *Service) Allowance(ctx context.Context, token, owner, spender common.Address) (*big.Int, error)
- func (s *Service) Approve(ctx context.Context, token, spender common.Address, amount *big.Int, ...) (*sdktypes.WriteResult, error)
- func (s *Service) ApproveService(ctx context.Context, token, operator common.Address, ...) (*sdktypes.WriteResult, error)
- func (s *Service) Balance(ctx context.Context, token, owner common.Address) (*big.Int, error)
- func (s *Service) ChainID() sdktypes.ChainID
- func (s *Service) Deposit(ctx context.Context, token, to common.Address, amount *big.Int, ...) (*sdktypes.WriteResult, error)
- func (s *Service) DepositWithPermit(ctx context.Context, token, to common.Address, amount, deadline *big.Int, ...) (*sdktypes.WriteResult, error)
- func (s *Service) DepositWithPermitAndApproveOperator(ctx context.Context, token, to common.Address, amount, deadline *big.Int, ...) (*sdktypes.WriteResult, error)
- func (s *Service) Fund(ctx context.Context, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
- func (s *Service) FundSync(ctx context.Context, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
- func (s *Service) GetRail(ctx context.Context, railID sdktypes.BigInt) (*RailView, error)
- func (s *Service) GetRailsAsPayee(ctx context.Context, payee, token common.Address, opts ...ListOption) (*RailPage, error)
- func (s *Service) GetRailsAsPayer(ctx context.Context, payer, token common.Address, opts ...ListOption) (*RailPage, error)
- func (s *Service) GetSettlementAmounts(ctx context.Context, railID sdktypes.BigInt, untilEpoch *big.Int) (*SettlementResult, error)
- func (s *Service) RevokeService(ctx context.Context, token, operator common.Address, opts ...WriteOption) (*sdktypes.WriteResult, error)
- func (s *Service) ServiceApproval(ctx context.Context, token, client, operator common.Address) (*OperatorApproval, error)
- func (s *Service) Settle(ctx context.Context, railID sdktypes.BigInt, untilEpoch *big.Int, ...) (*sdktypes.WriteResult, error)
- func (s *Service) SettleAuto(ctx context.Context, railID sdktypes.BigInt, untilEpoch *big.Int, ...) (*sdktypes.WriteResult, error)
- func (s *Service) SettleTerminatedRail(ctx context.Context, railID sdktypes.BigInt, opts ...WriteOption) (*sdktypes.WriteResult, error)
- func (s *Service) WalletBalance(ctx context.Context, token, account common.Address) (*big.Int, error)
- func (s *Service) Withdraw(ctx context.Context, token common.Address, amount *big.Int, ...) (*sdktypes.WriteResult, error)
- type SettlementResult
- type WriteOption
- type WriteResult
Examples ¶
Constants ¶
const PermitDeadlineDuration = time.Hour
PermitDeadlineDuration is the default validity window appended to the current wall-clock time when the caller does not provide an explicit permit deadline.
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, so errors.Is(err, payments.ErrClosed) matches either sentinel.
var ErrInsufficientAllowance = errors.New("payments: insufficient allowance")
ErrInsufficientAllowance is returned when an ERC20 allowance is lower than the amount required for a deposit.
var ErrInsufficientBalance = errors.New("payments: insufficient balance")
ErrInsufficientBalance is returned when the on-chain balance is lower than the requested amount for a withdrawal or transfer.
var ErrInvalidArgument = errors.New("payments: invalid argument")
ErrInvalidArgument is returned, wrapped via fmt.Errorf with %w, when a caller passes an argument that violates a precondition (nil pointer, zero address, invalid chain ID). Match with errors.Is(err, payments.ErrInvalidArgument).
Business-domain sentinels such as ErrInsufficientBalance or ErrInsufficientAllowance live alongside this file and cover runtime preconditions that are independent of caller-supplied arguments.
var ErrNothingToFund = errors.New("payments: nothing to fund (already approved and amount is 0)")
ErrNothingToFund is returned by Fund / FundSync when the account is already fully approved for WarmStorage and the caller requested a zero deposit amount, meaning there is no work to do.
var ErrPermitUnsupported = errors.New("payments: token contract does not support EIP-2612 permit")
ErrPermitUnsupported is returned by DepositWithPermit and DepositWithPermitAndApproveOperator when the token contract does not expose the EIP-2612 permit ABI (name / version / nonces probes fail). Callers can branch on this with errors.Is to fall back to Approve + Deposit instead of surfacing a generic precondition error.
var ErrTxFailed = types.ErrTxFailed
ErrTxFailed reports that a transaction was mined but reverted on-chain. Use errors.Is to match errors returned by state-changing calls.
This is an alias of types.ErrTxFailed kept for backwards compatibility; callers can match either interchangeably.
var ErrUninitialized = errors.New("payments: service not initialized; use payments.New")
ErrUninitialized is returned when a method is invoked on a zero-value Service (one that was not constructed via New). Match with errors.Is(err, payments.ErrUninitialized).
var ErrZeroAddress = errors.New("payments: zero address")
ErrZeroAddress is returned when a caller passes common.Address{} for an argument that must be a real token or account address. Public service methods wrap it together with ErrInvalidArgument so callers can match either the specific zero-address sentinel or the generic invalid-argument sentinel.
var LockupPeriodEpochs = big.NewInt(30 * 2880)
LockupPeriodEpochs is the default client-operator max lockup period granted when Fund auto-approves the WarmStorage operator: 30 days at 2880 epochs per day.
var ZeroAddress = common.Address{}
ZeroAddress is a convenience alias for common.Address{} used to indicate native FIL in WalletBalance queries.
Functions ¶
This section is empty.
Types ¶
type AccountState ¶
type AccountState struct {
Funds *big.Int
LockupCurrent *big.Int
LockupRate *big.Int
LockupLastSettledAt *big.Int
// FundedUntilEpoch is the forward-looking epoch at which the account's
// available funds will be exhausted at the current lockup rate.
// Sourced from getAccountInfoIfSettled(); zero when LockupRate is zero.
FundedUntilEpoch *big.Int
// contains filtered or unexported fields
}
AccountState mirrors FilPay.accounts(token, owner). All values are in base units of the payment token.
func (*AccountState) AvailableFunds ¶
func (a *AccountState) AvailableFunds() *big.Int
AvailableFunds returns Funds - LockupCurrent (never negative). A nil AccountState returns nil.
type Backend ¶
type Backend interface {
bind.ContractBackend
BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error)
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
BlockNumber(ctx context.Context) (uint64, error)
}
Backend is the minimal RPC surface used by the payments service. It is satisfied by *ethclient.Client. Tests can substitute a mock.
type ListOption ¶
type ListOption func(*listConfig)
ListOption tunes paginated list calls.
func WithListLimit ¶
func WithListLimit(limit *big.Int) ListOption
WithListLimit caps the number of results returned in one page. limit == 0 requests all remaining rails; negative values are ignored.
func WithListOffset ¶
func WithListOffset(offset *big.Int) ListOption
WithListOffset sets the starting offset for paginated results.
type OperatorApproval ¶
type OperatorApproval struct {
IsApproved bool
RateAllowance *big.Int // maximum per-epoch rate the operator may charge
LockupAllowance *big.Int // maximum lockup the operator may hold
RateUsage *big.Int // current per-epoch rate in use by the operator
LockupUsage *big.Int // current lockup held by the operator
MaxLockupPeriod *big.Int // maximum lockup period allowed (in epochs)
}
OperatorApproval mirrors FilPay.operatorApprovals(token, client, operator).
type Options ¶
type Options struct {
// Backend is the Ethereum RPC client. Required.
Backend Backend
// ChainID of the target FEVM chain. Required; must be > 0.
ChainID sdktypes.ChainID
// FilPayAddress is the Filecoin Pay contract address. Required.
FilPayAddress common.Address
// WarmStorageAddress is the FilecoinWarmStorageService contract address.
// Optional; required for Fund / FundSync smart-route helpers because
// they route through WarmStorage operator approval state. When zero
// Fund / FundSync return ErrInvalidArgument.
WarmStorageAddress common.Address
// USDFCTokenAddress is the USDFC (or other ERC-2612) token address
// used as the default for Fund / FundSync and for permit operations
// that do not receive an explicit token argument. Optional; callers
// may always pass a token explicitly to DepositWithPermit.
USDFCTokenAddress common.Address
// Signer is used to sign transactions. Required for write methods;
// may be nil when the Service is used for reads only.
Signer signer.EVMSigner
// Logger is optional. When nil, logging is disabled.
Logger *slog.Logger
// NonceManager is optional. The root synapse Client injects a shared
// coordinator across all write-capable services; standalone callers may
// leave this nil to create one for this Service.
NonceManager *txutil.NonceManager
// ReceiptWait overrides the default receipt polling timeout used by
// WithConfirmations when the call waits for a receipt but does not
// provide a more specific WithWait(timeout). Zero uses
// txutil.DefaultReceiptWaitConfig.
ReceiptWait time.Duration
// Lifecycle, when non-nil, ties this Service to the owning Client's
// close state. After the Lifecycle is closed, every method returns
// ErrClosed without touching the RPC backend. Nil is allowed for
// standalone use.
Lifecycle *lifecycle.Lifecycle
}
Options bundles the dependencies for constructing a Service.
type PermitOption ¶
type PermitOption func(*permitConfig)
PermitOption is reserved for future nonce / salt overrides. Currently unused; keep the type to preserve API stability once options land.
type RailListItem ¶
RailListItem is a single entry returned by GetRailsAsPayer / GetRailsAsPayee; it corresponds to `FilecoinPayV1RailInfo` on the contract side.
type RailPage ¶
type RailPage struct {
Rails []RailListItem
NextOffset *big.Int
Total *big.Int
}
RailPage is one page of rails plus pagination cursors.
type RailView ¶
type RailView struct {
Token common.Address
From common.Address
To common.Address
Operator common.Address
Validator common.Address
PaymentRate *big.Int
LockupPeriod *big.Int
LockupFixed *big.Int
SettledUpTo *big.Int
EndEpoch *big.Int
CommissionRateBps *big.Int
ServiceFeeRecipient common.Address
}
RailView is the flattened view of FilecoinPayV1RailView from the FilPay contract.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service provides read and write access to the Filecoin Pay contract plus convenience wrappers around ERC20 allowance management.
It is safe for concurrent use. All state-changing calls return a sdktypes.WriteResult whose Receipt is only populated when WithWait is supplied.
func (*Service) Account ¶
Account returns the EOA address used for writes, or the zero address when the service was constructed without a signer.
func (*Service) AccountInfo ¶
func (s *Service) AccountInfo(ctx context.Context, token, owner common.Address) (*AccountState, error)
AccountInfo returns the on-chain account record for (token, owner).
When token is ZeroAddress, native FIL is queried via BalanceAt and returned as AccountState.Funds. All lockup fields are zero because native FIL is not tracked by the FilPay contract.
func (*Service) Allowance ¶
func (s *Service) Allowance(ctx context.Context, token, owner, spender common.Address) (*big.Int, error)
Allowance returns the ERC20 allowance of owner towards spender for token.
func (*Service) Approve ¶
func (s *Service) Approve(ctx context.Context, token, spender common.Address, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
Approve calls ERC20.approve(spender, amount) on the given token.
spender is typically the FilPay contract address; use service.Address() for that convenience.
func (*Service) ApproveService ¶
func (s *Service) ApproveService(ctx context.Context, token, operator common.Address, rateAllowance, lockupAllowance, maxLockupPeriod *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
ApproveService calls FilPay.setOperatorApproval(token, operator, true, rateAllowance, lockupAllowance, maxLockupPeriod). Use RevokeService to clear the approval.
func (*Service) Deposit ¶
func (s *Service) Deposit(ctx context.Context, token, to common.Address, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
Deposit calls FilPay.deposit(token, to, amount). The caller must have first approved at least `amount` on the token contract for FilPay. When `to` is the zero address the caller's EOA is used.
func (*Service) DepositWithPermit ¶
func (s *Service) DepositWithPermit( ctx context.Context, token, to common.Address, amount, deadline *big.Int, opts ...WriteOption, ) (*sdktypes.WriteResult, error)
DepositWithPermit deposits `amount` of `token` into the Filecoin Pay contract on behalf of the signer in a single on-chain transaction by attaching an ERC-2612 permit signature. No prior ERC20 approval is required.
`to` is the credited depositor; when zero, defaults to the signer EOA. `deadline` is the permit expiry (unix seconds); when nil, now + PermitDeadlineDuration is used. `token` must be an ERC-2612 / ERC20Permit-compliant token (e.g. USDFC).
func (*Service) DepositWithPermitAndApproveOperator ¶
func (s *Service) DepositWithPermitAndApproveOperator( ctx context.Context, token, to common.Address, amount, deadline *big.Int, operator common.Address, rateAllowance, lockupAllowance, maxLockupPeriod *big.Int, opts ...WriteOption, ) (*sdktypes.WriteResult, error)
DepositWithPermitAndApproveOperator combines DepositWithPermit with a SetOperatorApproval in the same transaction. Use this to onboard a new client: deposit + grant WarmStorage (or another operator) the allowances it needs in a single click.
func (*Service) Fund ¶
func (s *Service) Fund(ctx context.Context, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
Fund is a smart deposit that auto-detects whether WarmStorage is already approved with sufficient allowances and routes to the correct on-chain call:
- needs approval + amount > 0 → DepositWithPermitAndApproveOperator
- needs approval + amount == 0 → ApproveService
- already approved + amount > 0 → DepositWithPermit
- already approved + amount == 0 → ErrNothingToFund
Fund requires WarmStorageAddress and USDFCTokenAddress to be set on the Options. Returns ErrInvalidArgument when either is zero.
amount must be non-nil. Callers that want an approval-only flow must pass big.NewInt(0) explicitly so an omitted amount cannot silently broadcast an approval transaction.
Pass WithFundNeedsFwssApproval to reuse a previously computed approval decision instead of re-reading on-chain state.
func (*Service) FundSync ¶
func (s *Service) FundSync(ctx context.Context, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
FundSync runs Fund and waits for the transaction to be mined. It is equivalent to Fund(..., WithWait(timeout)) with a sensible default timeout when the caller did not supply one.
func (*Service) GetRailsAsPayee ¶
func (s *Service) GetRailsAsPayee(ctx context.Context, payee, token common.Address, opts ...ListOption) (*RailPage, error)
GetRailsAsPayee lists rails where `payee` is the account being paid on `token`. Callers may paginate with WithListOffset / WithListLimit.
func (*Service) GetRailsAsPayer ¶
func (s *Service) GetRailsAsPayer(ctx context.Context, payer, token common.Address, opts ...ListOption) (*RailPage, error)
GetRailsAsPayer lists rails where `payer` is the account being charged for `token`. Callers may paginate with WithListOffset / WithListLimit.
func (*Service) GetSettlementAmounts ¶
func (s *Service) GetSettlementAmounts(ctx context.Context, railID sdktypes.BigInt, untilEpoch *big.Int) (*SettlementResult, error)
GetSettlementAmounts simulates FilPay.settleRail via eth_call and decodes the resulting amounts without broadcasting a transaction. Use it to preview how much would be settled to the payee / operator / network.
func (*Service) RevokeService ¶
func (s *Service) RevokeService(ctx context.Context, token, operator common.Address, opts ...WriteOption) (*sdktypes.WriteResult, error)
RevokeService clears a prior ApproveService by setting approved=false and all allowances to zero.
func (*Service) ServiceApproval ¶
func (s *Service) ServiceApproval(ctx context.Context, token, client, operator common.Address) (*OperatorApproval, error)
ServiceApproval returns the operator approval record for (token, client, operator).
func (*Service) Settle ¶
func (s *Service) Settle(ctx context.Context, railID sdktypes.BigInt, untilEpoch *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
Settle triggers a rail settlement up to `untilEpoch`. When `untilEpoch` is nil or zero, the current block number is used.
func (*Service) SettleAuto ¶
func (s *Service) SettleAuto(ctx context.Context, railID sdktypes.BigInt, untilEpoch *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
SettleAuto inspects the rail state and routes to Settle or SettleTerminatedRail automatically — terminated rails (endEpoch > 0) go through the emergency path, active rails through the standard path.
func (*Service) SettleTerminatedRail ¶
func (s *Service) SettleTerminatedRail(ctx context.Context, railID sdktypes.BigInt, opts ...WriteOption) (*sdktypes.WriteResult, error)
SettleTerminatedRail triggers the emergency-settlement path for a terminated rail. This bypasses the operator validator and pays in full; it can only be called by the client after the max settlement epoch has passed.
func (*Service) WalletBalance ¶
func (s *Service) WalletBalance(ctx context.Context, token, account common.Address) (*big.Int, error)
WalletBalance returns the EOA balance of token. When token is the zero address the native FIL balance is returned via BalanceAt. Otherwise the ERC20 balanceOf(account) is queried.
func (*Service) Withdraw ¶
func (s *Service) Withdraw(ctx context.Context, token common.Address, amount *big.Int, opts ...WriteOption) (*sdktypes.WriteResult, error)
Withdraw calls FilPay.withdraw(token, amount). The amount must not exceed AccountInfo.AvailableFunds (pre-check can be disabled via WithSkipPrecheck).
type SettlementResult ¶
type SettlementResult struct {
TotalSettledAmount *big.Int
TotalNetPayeeAmount *big.Int
TotalOperatorCommission *big.Int
TotalNetworkFee *big.Int
FinalSettledEpoch *big.Int
Note string
}
SettlementResult is the decoded return tuple of FilPay.settleRail.
type WriteOption ¶
type WriteOption func(*writeConfig)
WriteOption tunes the behaviour of a single state-changing call.
func WithConfirmations ¶
func WithConfirmations(n uint64) WriteOption
WithConfirmations requires N block confirmations in addition to WithWait. Has no effect unless WithWait is also passed with a positive timeout.
func WithFundNeedsFwssApproval ¶
func WithFundNeedsFwssApproval(needs bool) WriteOption
WithFundNeedsFwssApproval overrides Fund / FundSync's approval-state probe. When set, Fund skips isFwssMaxApproved and uses the supplied decision directly so prepare/execute flows can reuse a previously computed result.
func WithSkipPrecheck ¶
func WithSkipPrecheck() WriteOption
WithSkipPrecheck disables client-side balance / allowance / funds checks before broadcasting. Useful when the caller has already validated state or wants to probe an on-chain revert for diagnostic purposes.
func WithWait ¶
func WithWait(timeout time.Duration) WriteOption
WithWait makes the call block until the transaction is mined, or the given timeout elapses. Use zero or a negative duration to return as soon as the tx is broadcast (the default).
type WriteResult ¶
type WriteResult = sdktypes.WriteResult
WriteResult is kept as an alias for backwards compatibility.