Documentation
¶
Overview ¶
Package money is the ONE exact money value for the Hanzo stack: an amount in a currency, backed by github.com/hanzoai/decimal (big.Int fixed-point). Unlike the int64/uint64 money libraries (which cap around 19 digits — about $9.20 at 18 decimals), this holds a fiat cent AND an 18-decimal on-chain balance with equal exactness, because the value is a big.Int decimal. No float64 ever touches money.
The design is the community-standard money pattern (never floats, integer-exact, Amount + Currency, Split/Allocate so a division loses no sub-unit) with the precision ceiling removed. An Amount is IMMUTABLE. Arithmetic between two Amounts requires the SAME currency, so you can never silently add USD to EUR.
Index ¶
- Variables
- func ParseDecimal(s string) (decimal.Decimal, error)
- type Amount
- func Avg(amounts ...Amount) (Amount, error)
- func ConvertWithRate(amount Amount, to Currency, rate decimal.Decimal) Amount
- func FromCents(cents int64) Amount
- func FromEUR(minor int64) Amount
- func FromFloat(f float64, cur Currency) Amount
- func FromGBP(minor int64) Amount
- func FromHUSD(wei *big.Int) Amount
- func FromJPY(minor int64) Amount
- func FromMinor(units int64, cur Currency) Amount
- func FromMinorBig(units *big.Int, cur Currency) Amount
- func FromUSD(minor int64) Amount
- func Max(amounts ...Amount) (Amount, error)
- func Min(amounts ...Amount) (Amount, error)
- func New(v decimal.Decimal, cur Currency) Amount
- func Parse(s string, cur Currency) (Amount, error)
- func ParseAmount(s string, defaultCode ...string) (Amount, error)
- func ParseAmountEuropean(s string, defaultCode ...string) (Amount, error)
- func Sum(amounts ...Amount) (Amount, error)
- func Zero(cur Currency) Amount
- func (a Amount) Add(b Amount) (Amount, error)
- func (a Amount) Allocate(ratios ...int) ([]Amount, error)
- func (a Amount) AsMajorUnits() float64
- func (a Amount) Cmp(b Amount) int
- func (a Amount) Currency() Currency
- func (a Amount) Decimal() decimal.Decimal
- func (a Amount) Display() string
- func (a Amount) IsNeg() bool
- func (a Amount) IsZero() bool
- func (a Amount) MarshalJSON() ([]byte, error)
- func (a Amount) Minor() *big.Int
- func (a Amount) MinorString() string
- func (a Amount) Mul(factor decimal.Decimal) Amount
- func (a Amount) Neg() Amount
- func (a *Amount) Scan(src any) error
- func (a Amount) Sign() int
- func (a Amount) Split(n int) ([]Amount, error)
- func (a Amount) String() string
- func (a Amount) Sub(b Amount) (Amount, error)
- func (a *Amount) UnmarshalJSON(b []byte) error
- func (a Amount) Value() (driver.Value, error)
- type Currency
- type Exchange
Constants ¶
This section is empty.
Variables ¶
var ( USD = reg(Currency{"USD", 2, "$", "840", "US Dollar"}) EUR = reg(Currency{"EUR", 2, "€", "978", "Euro"}) GBP = reg(Currency{"GBP", 2, "£", "826", "Pound Sterling"}) JPY = reg(Currency{"JPY", 0, "¥", "392", "Yen"}) CNY = reg(Currency{"CNY", 2, "¥", "156", "Yuan Renminbi"}) CHF = reg(Currency{"CHF", 2, "Fr", "756", "Swiss Franc"}) CAD = reg(Currency{"CAD", 2, "$", "124", "Canadian Dollar"}) AUD = reg(Currency{"AUD", 2, "$", "036", "Australian Dollar"}) NZD = reg(Currency{"NZD", 2, "$", "554", "New Zealand Dollar"}) HKD = reg(Currency{"HKD", 2, "$", "344", "Hong Kong Dollar"}) SGD = reg(Currency{"SGD", 2, "$", "702", "Singapore Dollar"}) INR = reg(Currency{"INR", 2, "₹", "356", "Indian Rupee"}) KRW = reg(Currency{"KRW", 0, "₩", "410", "Won"}) BRL = reg(Currency{"BRL", 2, "R$", "986", "Brazilian Real"}) MXN = reg(Currency{"MXN", 2, "$", "484", "Mexican Peso"}) ZAR = reg(Currency{"ZAR", 2, "R", "710", "Rand"}) SEK = reg(Currency{"SEK", 2, "kr", "752", "Swedish Krona"}) NOK = reg(Currency{"NOK", 2, "kr", "578", "Norwegian Krone"}) DKK = reg(Currency{"DKK", 2, "kr", "208", "Danish Krone"}) PLN = reg(Currency{"PLN", 2, "zł", "985", "Zloty"}) AED = reg(Currency{"AED", 2, "د.إ", "784", "UAE Dirham"}) SAR = reg(Currency{"SAR", 2, "﷼", "682", "Saudi Riyal"}) TRY = reg(Currency{"TRY", 2, "₺", "949", "Turkish Lira"}) RUB = reg(Currency{"RUB", 2, "₽", "643", "Russian Ruble"}) )
Fiat (ISO 4217) — the common set; extend via Register for the long tail.
var ( USDC = reg(Currency{"USDC", 6, "$", "", "USD Coin"}) USDT = reg(Currency{"USDT", 6, "$", "", "Tether"}) BTC = reg(Currency{"BTC", 8, "₿", "", "Bitcoin"}) ETH = reg(Currency{"ETH", 18, "Ξ", "", "Ether"}) HUSD = reg(Currency{"HUSD", 18, "$", "", "Hanzo USD"}) // Hanzo USD stablecoin, ERC-20 )
Crypto / stablecoins — decimals are the token's on-chain decimals so an off-chain Amount and an on-chain balance share one integer scale.
var ( // ErrCurrencyMismatch is returned when an operation combines two different // (non-zero) currencies. ErrCurrencyMismatch = errors.New("money: currencies do not match") // ErrUnknownCurrency is returned when a currency code/number is not in the registry. ErrUnknownCurrency = errors.New("money: unknown currency") // ErrInvalidAmount is returned when an amount string cannot be parsed. ErrInvalidAmount = errors.New("money: invalid amount") // ErrNoRate is returned when an exchange rate is missing. ErrNoRate = errors.New("money: no exchange rate") // ErrNonPositive is returned when a positive value was required (split parts, ratios). ErrNonPositive = errors.New("money: value must be positive") )
Sentinel errors, matched with errors.Is.
Functions ¶
Types ¶
type Amount ¶
type Amount struct {
// contains filtered or unexported fields
}
Amount is an exact money value: a decimal in a currency. (Currency and the currency registry live in currency.go.)
func Avg ¶ added in v0.2.0
Avg returns the mean, rounded to the currency's decimals (half-away-from-zero). Errors on an empty list or a currency mismatch.
func ConvertWithRate ¶ added in v0.2.0
ConvertWithRate converts amount into `to` at an explicit rate (rounded to `to`'s decimals).
func FromFloat ¶ added in v0.2.0
FromFloat builds an Amount from a float — USE ONLY for converting user input; floats are imprecise, so prefer Parse for exact decimals. The float is rendered at the currency's decimals and parsed exactly from there.
func FromMinor ¶
FromMinor builds an Amount from an integer count of the currency's smallest unit (e.g. cents for USD): value = units × 10^-cur.Decimals.
func FromMinorBig ¶
FromMinorBig is FromMinor for a big.Int count (an on-chain wei balance).
func FromUSD ¶ added in v0.2.0
FromUSD builds a USD amount from integer cents. The FromXXX helpers mirror gocanto's convenience constructors; they take the currency's smallest unit.
func Min ¶ added in v0.2.0
Min returns the smallest amount (same currency). Errors on an empty list or a currency mismatch.
func ParseAmount ¶ added in v0.2.0
ParseAmount parses a human-entered money string — "$1,234.56", "EUR 250,75", "100.50 USD", "£99.99" — into an exact Amount. The currency comes from a leading symbol, or a code token (prefix or suffix), or the optional defaultCode. Thousands separators are handled; a comma-only decimal is treated as a thousands separator (use ParseAmountEuropean for "10,50" == 10.50).
func ParseAmountEuropean ¶ added in v0.2.0
ParseAmountEuropean is ParseAmount but treats a comma-only separator as the DECIMAL point ("€10,50" == €10.50).
func Sum ¶ added in v0.2.0
Sum adds all amounts, which must share a currency (a zero-value operand is agnostic). The empty sum is a zero-value Amount.
func (Amount) Add ¶
Add returns a + b. A zero-value operand adopts the other's currency; two different non-zero currencies error.
func (Amount) Allocate ¶ added in v0.2.0
Allocate distributes the amount across the given integer ratios, summing EXACTLY to the original at the currency's minor-unit granularity — each part floors, then the leftover minor units go one-at-a-time to the leading parts. Ratios must be non-negative with a positive total.
func (Amount) AsMajorUnits ¶ added in v0.2.0
AsMajorUnits returns the value as a float in major units (e.g. dollars) — for DISPLAY only; never round-trip money through it.
func (Amount) Cmp ¶
Cmp reports −1,0,+1 as a <,==,> b. A zero-value operand is currency-agnostic; two different non-zero currencies panic (comparing USD to EUR is a bug, not a runtime condition — check Currency first for untrusted inputs).
func (Amount) Display ¶
Display renders the value at the currency's decimals with grouped thousands and the currency symbol ("$1,234.56", "¥10000", "100,003.01 HUSD" when no symbol). Exact — derived from the integer value, not a float.
func (Amount) MarshalJSON ¶
MarshalJSON emits {"amount":"<decimal>","currency":"USD"} — exact strings, no float.
func (Amount) Minor ¶
Minor returns the value as a big.Int count of the currency's smallest unit (round-half-up on any sub-unit precision) — the storage/on-chain integer.
func (Amount) MinorString ¶
MinorString is the minor-unit integer as a decimal string (the canonical storage form).
func (Amount) Mul ¶
Mul scales the amount by an exact decimal factor (e.g. a token count or a fee rate), keeping the currency.
func (Amount) Split ¶
Split divides the amount into n parts that sum EXACTLY to the original at the currency's minor-unit granularity — the remainder is distributed one minor unit at a time to the leading parts, so no sub-unit is created or lost. n must be positive.
func (*Amount) UnmarshalJSON ¶ added in v0.2.0
UnmarshalJSON parses {"amount","currency"} exactly (a known code resolves to its full Currency; an unknown code is kept as a bare code).
type Currency ¶
type Currency struct {
Code string // ISO-4217 alpha code or custom ("USD", "HUSD")
Decimals int32 // fractional digits of the smallest unit
Symbol string // display grapheme ("$", "€", "₿")
Numeric string // ISO-4217 numeric code ("840"); "" for custom
Name string
}
Currency is a currency's identity: its ISO-4217 (or custom) code, the number of decimal places in its smallest unit (Decimals — USD 2, JPY 0, an 18-decimal ERC-20 18), a display Symbol, and the ISO numeric code where applicable. Custom currencies (crypto, loyalty points) are first-class — construct one directly or Register it.
type Exchange ¶ added in v0.2.0
type Exchange struct {
// contains filtered or unexported fields
}
Exchange is an in-memory table of conversion rates. A rate from → to means one unit of `from` buys `rate` units of `to`. Not safe for concurrent writes; build it once, then read.
func NewExchange ¶ added in v0.2.0
func NewExchange() *Exchange
NewExchange returns an empty rate table.
func (*Exchange) AddRate ¶ added in v0.2.0
AddRate registers (or replaces) the from→to rate from a decimal string ("0.85"). The inverse is NOT implied — add it explicitly if you need both directions.