currency

package
v1.49.60 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 5 Imported by: 1

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Types = []Type{}/* 139 elements not displayed */

Functions

This section is empty.

Types

type Cents

type Cents int64

Cents is an amount in a currency's minor units — despite the name it is minor units, not cents: for a zero-decimal currency (see Type.IsZeroDecimal) one Cents is one whole unit.

There is deliberately no parser here. Converting a decimal string of MAJOR units ("19.99") into minor units is one fact, and its home is money.ParseCents in github.com/hanzoai/money — which commerce already depends on. Call that and convert the int64 it returns.

func (Cents) BasisPoints added in v1.49.49

func (c Cents) BasisPoints(bps int) Cents

BasisPoints returns bps basis points of c, rounded half away from zero — the shape promotion application methods store a percentage in (1500 means 15.00%).

func (Cents) Fake

func (c Cents) Fake() Cents

func (Cents) FakeN

func (c Cents) FakeN(max int) Cents

func (Cents) Percent added in v1.49.49

func (c Cents) Percent(pct int) Cents

Percent returns pct percent of c, rounded half away from zero — the shape coupons and discount rules store a percentage in (10 means 10%, not 0.10).

func (Cents) Scale added in v1.49.49

func (c Cents) Scale(rate decimal.Decimal) Cents

Scale returns c scaled by an exact rate — a discount, a commission, a tax — rounded to a whole minor unit HALF AWAY FROM ZERO. It is the one way to take a percentage of an amount in this codebase; the arithmetic itself is money.ScaleMinor, for the same reason the parser above is money.ParseCents.

The rule is rounding, not truncation, and it is the rule everywhere rather than one rule for discounts and another for fees. 10% off $19.99 is $1.999: truncating gives $1.99 and keeps the tenth of a cent, rounding gives $2.00 and gives it away. Either is defensible once; what is not defensible is that the fraction always fell the same way, so a price book's worth of orders each quietly withheld a fraction of a cent from the customer and the sum was never zero.

Half away from zero also means a negative scales like the positive it reverses, so a refunded discount is the discount back — which math.Floor, rounding toward negative infinity, does not give.

PANICS if the result does not fit an int64. Cents is an int64, so the only inputs that can do this are an amount already near the type's limit scaled up by a rate above 1 — no order reaches $46 quadrillion, and a discount rate is at most 1 anyway. Returning a wrapped number instead would report money nobody owes, and returning zero would report a free order; this follows money.Amount.Cmp, which panics across currencies on the same reasoning: it is a bug in the caller, not a runtime condition to branch on.

func (Cents) ScaleCeil added in v1.49.51

func (c Cents) ScaleCeil(rate decimal.Decimal) Cents

ScaleCeil and ScaleFloor are Scale for the amounts whose DIRECTION is the policy rather than an artifact: the platform fee this codebase has always rounded up, the affiliate commission it has always rounded down and kept the remainder of. Scale's half away from zero is right for an amount that only has to be correct, and wrong for one somebody decided always falls the same way — so those keep their direction, and only stop being computed on a float.

They round toward +infinity and toward -infinity, not away from and toward zero. A fee reversed on a refund is negative, and there the two readings differ.

The float spellings they replace, math.Ceil(float64(c)*rate) and math.Floor, do not round the product — they round the FLOAT, which is a different number and wrong in the direction each caller cares about most. 0.07 is held a hair high, so 700 cents at 7% is 49.000000000000007 and ceilings to 50: a cent charged on an amount that was exactly 49. 0.29 is held a hair low, so 100 cents at 29% is 28.999999999999996 and floors to 28: a cent taken out of a commission that was exactly 29. money.ScaleMinorCeil/Floor form the product exactly, so a whole product survives rounding in either direction untouched.

PANICS on overflow, for the reason Scale does.

func (Cents) ScaleFloor added in v1.49.51

func (c Cents) ScaleFloor(rate decimal.Decimal) Cents

ScaleFloor returns c scaled by rate, rounded toward -infinity. See ScaleCeil.

type Type

type Type string
const (
	USD Type = "usd"
	AUD Type = "aud"
	CAD Type = "cad"
	EUR Type = "eur"
	GBP Type = "gbp"
	HKD Type = "hkd"
	JPY Type = "jpy"
	NZD Type = "nzd"
	SGD Type = "sgd"
	AED Type = "aed" // United Arab Emirates Dirham
	AFN Type = "afn" // Afghan Afghani*
	ALL Type = "all" // Albanian Lek
	AMD Type = "amd" // Armenian Dram
	ANG Type = "ang" // Netherlands Antillean Gulden
	AOA Type = "aoa" // Angolan Kwanza*
	ARS Type = "ars" // Argentine Peso*
	AWG Type = "awg" // Aruban Florin
	AZN Type = "azn" // Azerbaijani Manat
	BAM Type = "bam" // Bosnia & Herzegovina Convertible Mark
	BBD Type = "bbd" // Barbadian Dollar
	BDT Type = "bdt" // Bangladeshi Taka
	BGN Type = "bgn" // Bulgarian Lev
	BIF Type = "bif" // Burundian Franc
	BMD Type = "bmd" // Bermudian Dollar
	BND Type = "bnd" // Brunei Dollar
	BOB Type = "bob" // Bolivian Boliviano*
	BRL Type = "brl" // Brazilian Real*
	BSD Type = "bsd" // Bahamian Dollar
	BWP Type = "bwp" // Botswana Pula
	BZD Type = "bzd" // Belize Dollar
	CDF Type = "cdf" // Congolese Franc
	CHF Type = "chf" // Swiss Franc
	CLP Type = "clp" // Chilean Peso*
	CNY Type = "cny" // Chinese Renminbi Yuan
	COP Type = "cop" // Colombian Peso*
	CRC Type = "crc" // Costa Rican Colón*
	CVE Type = "cve" // Cape Verdean Escudo*
	CZK Type = "czk" // Czech Koruna*
	DJF Type = "djf" // Djiboutian Franc*
	DKK Type = "dkk" // Danish Krone
	DOP Type = "dop" // Dominican Peso
	DZD Type = "dzd" // Algerian Dinar
	EEK Type = "eek" // Estonian Kroon*
	EGP Type = "egp" // Egyptian Pound
	ETB Type = "etb" // Ethiopian Birr
	FJD Type = "fjd" // Fijian Dollar
	FKP Type = "fkp" // Falkland Islands Pound*
	GEL Type = "gel" // Georgian Lari
	GIP Type = "gip" // Gibraltar Pound
	GMD Type = "gmd" // Gambian Dalasi
	GNF Type = "gnf" // Guinean Franc*
	GTQ Type = "gtq" // Guatemalan Quetzal*
	GYD Type = "gyd" // Guyanese Dollar
	HNL Type = "hnl" // Honduran Lempira*
	HRK Type = "hrk" // Croatian Kuna
	HTG Type = "htg" // Haitian Gourde
	HUF Type = "huf" // Hungarian Forint*
	IDR Type = "idr" // Indonesian Rupiah
	ILS Type = "ils" // Israeli New Sheqel
	INR Type = "inr" // Indian Rupee*
	ISK Type = "isk" // Icelandic Króna
	JMD Type = "jmd" // Jamaican Dollar
	KES Type = "kes" // Kenyan Shilling
	KGS Type = "kgs" // Kyrgyzstani Som
	KHR Type = "khr" // Cambodian Riel
	KMF Type = "kmf" // Comorian Franc
	KRW Type = "krw" // South Korean Won
	KYD Type = "kyd" // Cayman Islands Dollar
	KZT Type = "kzt" // Kazakhstani Tenge
	LAK Type = "lak" // Lao Kip*
	LBP Type = "lbp" // Lebanese Pound
	LKR Type = "lkr" // Sri Lankan Rupee
	LRD Type = "lrd" // Liberian Dollar
	LSL Type = "lsl" // Lesotho Loti
	LTL Type = "ltl" // Lithuanian Litas
	LVL Type = "lvl" // Latvian Lats
	MAD Type = "mad" // Moroccan Dirham
	MDL Type = "mdl" // Moldovan Leu
	MGA Type = "mga" // Malagasy Ariary
	MKD Type = "mkd" // Macedonian Denar
	MNT Type = "mnt" // Mongolian Tögrög
	MOP Type = "mop" // Macanese Pataca
	MRO Type = "mro" // Mauritanian Ouguiya
	MUR Type = "mur" // Mauritian Rupee*
	MVR Type = "mvr" // Maldivian Rufiyaa
	MWK Type = "mwk" // Malawian Kwacha
	MXN Type = "mxn" // Mexican Peso*
	MYR Type = "myr" // Malaysian Ringgit
	MZN Type = "mzn" // Mozambican Metical
	NAD Type = "nad" // Namibian Dollar
	NGN Type = "ngn" // Nigerian Naira
	NIO Type = "nio" // Nicaraguan Córdoba*
	NOK Type = "nok" // Norwegian Krone
	NPR Type = "npr" // Nepalese Rupee
	PAB Type = "pab" // Panamanian Balboa*
	PEN Type = "pen" // Peruvian Nuevo Sol*
	PGK Type = "pgk" // Papua New Guinean Kina
	PHP Type = "php" // Philippine Peso
	PKR Type = "pkr" // Pakistani Rupee
	PLN Type = "pln" // Polish Złoty
	PYG Type = "pyg" // Paraguayan Guaraní*
	QAR Type = "qar" // Qatari Riyal
	RON Type = "ron" // Romanian Leu
	RSD Type = "rsd" // Serbian Dinar
	RUB Type = "rub" // Russian Ruble
	RWF Type = "rwf" // Rwandan Franc
	SAR Type = "sar" // Saudi Riyal
	SBD Type = "sbd" // Solomon Islands Dollar
	SCR Type = "scr" // Seychellois Rupee
	SEK Type = "sek" // Swedish Krona
	SHP Type = "shp" // Saint Helenian Pound*
	SLL Type = "sll" // Sierra Leonean Leone
	SOS Type = "sos" // Somali Shilling
	SRD Type = "srd" // Surinamese Dollar*
	STD Type = "std" // São Tomé and Príncipe Dobra
	SVC Type = "svc" // Salvadoran Colón*
	SZL Type = "szl" // Swazi Lilangeni
	THB Type = "thb" // Thai Baht
	TJS Type = "tjs" // Tajikistani Somoni
	TOP Type = "top" // Tongan Paʻanga
	TRY Type = "try" // Turkish Lira
	TTD Type = "ttd" // Trinidad and Tobago Dollar
	TWD Type = "twd" // New Taiwan Dollar
	TZS Type = "tzs" // Tanzanian Shilling
	UAH Type = "uah" // Ukrainian Hryvnia
	UGX Type = "ugx" // Ugandan Shilling
	UYU Type = "uyu" // Uruguayan Peso*
	UZS Type = "uzs" // Uzbekistani Som
	VND Type = "vnd" // Vietnamese Đồng
	VUV Type = "vuv" // Vanuatu Vat
	UWT Type = "uwt" // Samoan Tala
	XAF Type = "xaf" // Central African Cfa Franc
	XCD Type = "xcd" // East Caribbean Dollar
	XOF Type = "xof" // West African Cfa Franc*
	XPF Type = "xpf" // Cfp Franc*
	YER Type = "yer" // Yemeni Rial
	ZAR Type = "zar" // South African Rand
	ZMW Type = "zmw" // Zambian Kwacha

	// Three-decimal fiat (ISO 4217). These are real decimal places, not a
	// rounding convention: one Kuwaiti dinar is 1000 fils.
	BHD Type = "bhd" // Bahraini Dinar
	IQD Type = "iqd" // Iraqi Dinar
	JOD Type = "jod" // Jordanian Dinar
	KWD Type = "kwd" // Kuwaiti Dinar
	LYD Type = "lyd" // Libyan Dinar
	OMR Type = "omr" // Omani Rial
	TND Type = "tnd" // Tunisian Dinar

	// Crypto. The minor unit is the chain's own smallest indivisible unit —
	// satoshi, wei, lamport, nanoton — not a two-decimal fiat convention.
	BTC   Type = "btc"   // Bitcoin, 8 (satoshi)
	XBT   Type = "xbt"   // Bitcoin, ISO-style code
	BCH   Type = "bch"   // Bitcoin Cash, 8
	LTC   Type = "ltc"   // Litecoin, 8
	DOGE  Type = "doge"  // Dogecoin, 8
	SOL   Type = "sol"   // Solana, 9 (lamport)
	TON   Type = "ton"   // Toncoin, 9 (nanoton)
	XRP   Type = "xrp"   // XRP, 6 (drop)
	USDC  Type = "usdc"  // USD Coin, 6
	USDT  Type = "usdt"  // Tether, 6
	ETH   Type = "eth"   // Ethereum, 18 (wei)
	MATIC Type = "matic" // Polygon, 18
	AVAX  Type = "avax"  // Avalanche, 18
	SHIB  Type = "shib"  // Shiba Inu, 18

	// Own chains. EVM-native, so 18 like any other EVM gas token.
	LUX   Type = "lux"   // Lux C-Chain, 18 (X/P-Chain LUX is 9 — see decimals)
	ZOO   Type = "zoo"   // Zoo, 18
	AI    Type = "ai"    // Hanzo native gas, 18
	HANZO Type = "hanzo" // Hanzo, alias of AI
	SPC   Type = "spc"   // Sparkle Pony, 18
	PARS  Type = "pars"  // Pars Network, 18
	HUSD  Type = "husd"  // Hanzo USD, 18

	PNT Type = "points" // points, 0 — a point is indivisible
)

func Fake

func Fake() Type

func (Type) Amount added in v1.49.48

func (t Type) Amount(c Cents) money.Amount

Amount lifts a minor-unit amount in this currency into an exact money.Amount.

This is the ONE conversion out of Cents, and every rendering hangs off it: .MajorString() for a decimal string on the wire, .Display() for a human, .AsMajorUnits() for the last inch of a third-party API whose schema demands a JSON number. commerce owns no arithmetic of its own here — money does, on a big.Int, so no rendering can lose a cent or invent one.

func (Type) Code

func (t Type) Code() string

Give the currency's Code

func (Type) Decimals added in v1.49.48

func (t Type) Decimals() int32

Decimals is how many fractional digits the currency's minor unit has. This is the ONE place that scale is decided; nothing else may hardcode a 100.

func (Type) FitsCents added in v1.49.59

func (t Type) FitsCents() bool

FitsCents reports whether this currency's minor units fit the int64 that Cents is. They do not for an 18-decimal token: one ETH is 1e18 wei and an int64 tops out at 9.2e18, so Cents cannot hold ten of them. Those amounts have to travel as money.Amount, which is arbitrary-precision.

func (Type) FromMinimalUnits

func (t Type) FromMinimalUnits(b *big.Int) Cents

func (Type) IsCrypto

func (t Type) IsCrypto() bool

Is this a supported cryptocurrency

func (Type) IsZeroDecimal

func (t Type) IsZeroDecimal() bool

Does the currency not have a decimal convention such as Japanese Yen (¥100) instead of USD ($1.00)

func (Type) Label

func (t Type) Label() string

Give the currency's Symbol + Code string

func (Type) MinimalUnitFactor

func (t Type) MinimalUnitFactor() *big.Int

Since pricing things in a crypto minimal denomination exceed int64 and the minimal domination is worth so little, we generally use a larger denomination of the currency by convention that can capture the minimal relatable values.

This returns the ratio of convention denomination to minimal denomination

func (Type) Money added in v1.49.48

func (t Type) Money() money.Currency

Money lifts this currency into github.com/hanzoai/money — the ONE bridge between commerce's currency table and the package that owns exact money.

func (Type) Parse added in v1.49.52

func (t Type) Parse(s string) (Cents, error)

Parse is the inverse of ToStringNoSymbol: it reads a decimal string in this currency's major unit and returns exact minor units.

It exists so an amount that arrives as a DECIMAL never has to pass through a float64 to become Cents. "19.99" has no exact binary representation, so Cents(f*100) on a parsed float yields 1998 — a cent lost, on money that was already captured. The scale comes from this package's own currency table rather than money's registry, which knows 29 of the 142 currencies here.

func (Type) ParseAmount added in v1.49.59

func (t Type) ParseAmount(s string) (money.Amount, error)

ParseAmount reads a decimal string of MAJOR units into an exact amount at this currency's own scale, with no int64 anywhere on the path.

This is the conversion to reach for when the currency might be an 18-decimal token: one ETH is 1e18 wei, so Parse (which returns Cents, an int64) can only carry nine of them before it overflows. money.Amount is arbitrary-precision — a big.Int underneath — so it holds a wei and a whale balance alike.

func (Type) Symbol

func (t Type) Symbol() string

Give the currency's symbol

func (Type) ToMinimalUnits

func (t Type) ToMinimalUnits(c Cents) *big.Int

func (Type) ToString

func (t Type) ToString(c Cents) string

ToString renders the amount with its symbol ("$10.99", "-$19.99").

func (Type) ToStringNoSymbol

func (t Type) ToStringNoSymbol(c Cents) string

ToStringNoSymbol renders the amount as a plain fixed-scale decimal string ("10.99", "500" for a zero-decimal currency, "-19.99" for a refund).

Jump to

Keyboard shortcuts

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