Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

feeledger source pure

Package feeledger is a pure accounting primitive for realms that hold coins on behalf of users and charge an explicit...

Overview

Package feeledger is a pure accounting primitive for realms that hold coins on behalf of users and charge an explicit protocol fee on deposits. It tracks per-account balances, the sum of user liabilities, and a separately-accrued fee pot. It never touches coins itself: the importing realm moves coins and drives this ledger, keeping the two in lock-step so that

Example
1coins held by realm == UsersTotal() + FeesAccrued() + surplus

where surplus is coins pushed to the realm outside the ledger's flow (always >= 0, and 0 if every coin movement goes through the ledger).

Fee model:

  • Fees are expressed in basis points (1 bps = 0.01%); BpsDenominator is 10000, so bps == 10000 means the whole deposit is fee.
  • fee = floor(amount * bps / 10000). Rounding always favors the DEPOSITOR: any fractional fee is dropped, the account is credited amount - fee. A small deposit may therefore pay zero fee.
  • There is no minimum fee. The maximum fee is bounded by the per-ledger cap set at construction (maxFeeBps <= 10000), so a fee can never exceed its deposit.
  • bps == 0 is a valid configuration: fee is exactly 0 and the full amount is credited.

All failures are returned as errors and leave the ledger COMPLETELY UNCHANGED; callers in realms typically wrap calls so an error panics and aborts the transaction. Must* wrappers are provided and are the only functions in this package that panic.

The ledger is address-agnostic: accounts are non-empty strings. Realms normally use address.String().

Constants 1

const BpsDenominator

1const BpsDenominator = int64(10000)
source

BpsDenominator is the fee basis: fees are bps/BpsDenominator of the deposited amount.

Variables 1

var ErrEmptyAccount, ErrInvalidAmount, ErrInvalidBps, ErrInsufficient, ErrOverflow

1var (
2	ErrEmptyAccount  = errors.New("feeledger: empty account key")
3	ErrInvalidAmount = errors.New("feeledger: amount must be positive")
4	ErrInvalidBps    = errors.New("feeledger: fee bps out of range")
5	ErrInsufficient  = errors.New("feeledger: insufficient balance")
6	ErrOverflow      = errors.New("feeledger: int64 overflow")
7)
source

Errors returned by Ledger operations.

Functions 3

func FeeFor

1func FeeFor(amount, bps int64) (int64, error)
source

FeeFor returns the fee charged on amount at bps, using the ledger's rounding rule: floor(amount * bps / BpsDenominator). It is a pure preview — no state is read or written beyond validation against BpsDenominator (NOT the ledger cap; use it to inspect any policy). amount must be >= 0 and bps in [0, BpsDenominator].

func MustNew

1func MustNew(maxFeeBps int64) *Ledger
source

MustNew is New but panics on error.

func New

1func New(maxFeeBps int64) (*Ledger, error)
source

New returns an empty ledger that rejects deposit fees above maxFeeBps. maxFeeBps must be in [0, BpsDenominator].

Types 1

type Ledger

struct
1type Ledger struct {
2	maxFeeBps   int64
3	balances    *avl.Tree // account string -> int64 (always > 0)
4	usersTotal  int64     // == sum of all balances
5	feesAccrued int64     // fees charged but not yet withdrawn
6}
source

Ledger tracks per-account balances, their sum (user liabilities), and separately-accrued protocol fees. The zero value is not usable; construct with New.

Methods on Ledger

func Accounts

method on Ledger
1func (l *Ledger) Accounts() int
source

Accounts returns the number of accounts with a non-zero balance.

func BalanceOf

method on Ledger
1func (l *Ledger) BalanceOf(account string) int64
source

BalanceOf returns account's balance, or 0 if absent.

func Deposit

method on Ledger
1func (l *Ledger) Deposit(account string, amount, feeBps int64) (credited, fee int64, err error)
source

Deposit credits account with amount minus the fee at feeBps, accruing the fee to the fee pot. Returns the credited amount and the fee (credited + fee == amount always). Fails with ErrEmptyAccount, ErrInvalidAmount (amount <= 0), ErrInvalidBps (feeBps outside [0, MaxFeeBps]), or ErrOverflow if the account balance or total liabilities would leave int64 range. On error nothing is modified.

func FeesAccrued

method on Ledger
1func (l *Ledger) FeesAccrued() int64
source

FeesAccrued returns the fee pot: charged but not yet withdrawn.

func Iterate

method on Ledger
1func (l *Ledger) Iterate(fn func(account string, balance int64) bool)
source

Iterate calls fn for each account in sorted order with its balance. Iteration stops early when fn returns true.

func Liabilities

method on Ledger
1func (l *Ledger) Liabilities() int64
source

Liabilities returns UsersTotal() + FeesAccrued() — everything the importing realm owes. Deposit guarantees this sum fits in int64.

func MaxFeeBps

method on Ledger
1func (l *Ledger) MaxFeeBps() int64
source

MaxFeeBps returns the ledger's hard fee cap.

func MustDeposit

method on Ledger
1func (l *Ledger) MustDeposit(account string, amount, feeBps int64) (credited, fee int64)
source

MustDeposit is Deposit but panics on error.

func MustWithdraw

method on Ledger
1func (l *Ledger) MustWithdraw(account string, amount int64)
source

MustWithdraw is Withdraw but panics on error.

func UsersTotal

method on Ledger
1func (l *Ledger) UsersTotal() int64
source

UsersTotal returns the sum of all account balances (user liabilities).

func Withdraw

method on Ledger
1func (l *Ledger) Withdraw(account string, amount int64) error
source

Withdraw debits amount from account. Fails with ErrEmptyAccount, ErrInvalidAmount (amount <= 0), or ErrInsufficient if the balance is smaller than amount. A balance drained to zero is removed from storage. On error nothing is modified.

func WithdrawAll

method on Ledger
1func (l *Ledger) WithdrawAll(account string) (int64, error)
source

WithdrawAll drains account's entire balance and returns it. Returns (0, nil) if the account holds nothing. Fails only with ErrEmptyAccount.

func WithdrawFees

method on Ledger
1func (l *Ledger) WithdrawFees() int64
source

WithdrawFees drains the accrued fee pot and returns the amount (0 if nothing has accrued). Never fails.

Imports 2

Source Files 2