Cosmic Bull

Pure package on pearl-1

feeledger

gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/feeledger

pure packageprimitiveaccounting

RenderedSourceCall builder

curated

Per-account balance ledger with an explicit basis-point fee pot; error-pure and overflow-checked. Conservation contract: held == UsersTotal + FeesAccrued + surplus.

Identity

Import pathgno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/feeledger
Kindpure package (/p/)
Chainpearl-1
Namespaceg1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3
Realm addressnone — A /p/ package is not a realm: it holds no state, custodies no coins and is never a transaction sender. The pkgPath derivation would still produce a value; recording one would name nothing.

Provenance

chain-attested
Deployed at height572,441
Deploy transactionfeb4b559aecd184494f4c0786732efce263626811edd4f4bacfb2b9563c1f2a0 look it up on the RPC
Deployerg1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3
Gas used17,459,924
Storage11,976 bytes, deposit 1197600ugnot
Files on chainfeeledger.gno gnomod.toml
Deployed bytesfeeledger.gno — 8,723 bytes
sha256bb2e1058973d31b09a5e6be99c4cd60f2ef155a64eb259191fcfd590dcea0d9f

Do not take the hash above on trust. $download returns the bytes pearl-1 is actually running; this command fetches them and prints their digest, which should equal the one in the table:

curl -sS 'https://pearl.testnets.gno.land/p/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/feeledger$download&file=feeledger.gno' | shasum -a 256

Expected: bb2e1058973d31b09a5e6be99c4cd60f2ef155a64eb259191fcfd590dcea0d9f — 8,723 bytes. This was checked for all 21 packages while building this site's architecture record; every one matched. Use curl: pearl's edge answers Python's default user-agent with HTTP 403.

API

chain-derived 3 exported functions, 1 type, 13 methods.

This is a /p/ package: you import it, you do not call it in a transaction. gnoweb's $help shows only exported top-level functions, so the types and methods below do not appear there at all — which is why this reference exists.

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

coins 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:

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

Imports

Constants and variables

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

const BpsDenominator = int64(10000)

Errors returned by Ledger operations.

var (
	ErrEmptyAccount  = errors.New("feeledger: empty account key")
	ErrInvalidAmount = errors.New("feeledger: amount must be positive")
	ErrInvalidBps    = errors.New("feeledger: fee bps out of range")
	ErrInsufficient  = errors.New("feeledger: insufficient balance")
	ErrOverflow      = errors.New("feeledger: int64 overflow")
)

Types

type Ledger

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

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

Ledger.Accounts

func (l *Ledger) Accounts() int

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

Ledger.BalanceOf

func (l *Ledger) BalanceOf(account string) int64

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

Ledger.Deposit

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

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.

Ledger.FeesAccrued

func (l *Ledger) FeesAccrued() int64

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

Ledger.Iterate

func (l *Ledger) Iterate(fn func(account string, balance int64) bool)

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

Ledger.Liabilities

func (l *Ledger) Liabilities() int64

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

Ledger.MaxFeeBps

func (l *Ledger) MaxFeeBps() int64

MaxFeeBps returns the ledger's hard fee cap.

Ledger.MustDeposit

func (l *Ledger) MustDeposit(account string, amount, feeBps int64) (credited, fee int64)

MustDeposit is Deposit but panics on error.

Ledger.MustWithdraw

func (l *Ledger) MustWithdraw(account string, amount int64)

MustWithdraw is Withdraw but panics on error.

Ledger.UsersTotal

func (l *Ledger) UsersTotal() int64

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

Ledger.Withdraw

func (l *Ledger) Withdraw(account string, amount int64) error

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.

Ledger.WithdrawAll

func (l *Ledger) WithdrawAll(account string) (int64, error)

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

Ledger.WithdrawFees

func (l *Ledger) WithdrawFees() int64

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

Functions

FeeFor

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

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].

MustNew

func MustNew(maxFeeBps int64) *Ledger

MustNew is New but panics on error.

New

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

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


Doc text is reproduced as vm/qdoc returns it. The node markdown-escapes doc comments, so a bracket or angle bracket may carry a backslash the committed source does not have. The source itself is at source and in this repository.

Dependencies

chain-attested
Importserrors, gno.land/p/nt/avl/v0
First-party dependenciesnone
Used bybounties, bounty_panel, coindemo, grants, market, service_market, subscriptions, vault

Known limitations

Recorded by the people who built and deployed it. This list is deliberately not empty where honesty costs something.

curated

Source and records

Source filepearl/p/feeledger/feeledger.gno at commit 6a510c665a53 in the project repository (not public — the digest command above is the check that needs no repository)
Matches the deployed bytesyes — byte-identical
Registered ingno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/service_registry as feeledger (type library)
Recordscatalog/primitives.md#feeledger
pearl/DEPLOYMENT.md