Skip to content

Money Representation

Money handling is the most critical part of a financial system. FWallet follows strict rules to ensure amounts are never corrupted by floating-point arithmetic or JSON serialization.

The Rules

  1. All amounts are stored as bigint in the database, in the smallest unit of the currency.
  2. No floating-point arithmetic on money. Ever. All calculations use integer math.
  3. API responses return amounts as strings to avoid JSON number precision issues (JavaScript’s Number type loses precision above 2^53).

Currency Table

FWallet supports these currencies, each with a defined number of decimal places:

CurrencyCodeDecimalsMultiplierExample: “10,000” in display
Ugandan ShillingUGX0110000
Kenyan ShillingKES21001000000
Tanzanian ShillingTSH0110000
US DollarUSD21001000000
Chinese YuanCNY21001000000
British PoundGBP21001000000

How to Read the Table

  • Decimals = number of fractional digits the currency has
  • Multiplier = 10 ^ decimals. This is what you multiply a human-readable amount by to get the integer stored in the API.
  • Example = the integer value that represents “10,000” in human-readable form

For UGX (0 decimals): 10,000 UGX is stored as 10000. What you see is what you store.

For USD (2 decimals): $10,000.00 is stored as 1000000 (10,000 x 100). The API stores cents, not dollars.

Converting Between Display and API Values

Display to API (when sending requests)

Multiply the human-readable amount by the multiplier:

API value = display amount x 10^decimals

Examples:

  • 500,000 UGX -> 500000 (x 1)
  • $250.50 USD -> 25050 (x 100)
  • 1,000.00 KES -> 100000 (x 100)

API to Display (when showing to users)

Divide the API value by the multiplier:

Display amount = API value / 10^decimals

Examples:

  • 500000 UGX -> 500,000 UGX (/ 1)
  • 25050 USD -> $250.50 (/ 100)
  • 100000 KES -> 1,000.00 KES (/ 100)

API Request Format

When sending amounts in API requests, use integers:

{
"amount": 500000,
"currencyCode": "UGX"
}
{
"amount": 25050,
"currencyCode": "USD"
}

API Response Format

Amounts in API responses are returned as strings:

{
"balance": "500000",
"amount": "100000",
"fee": "2000"
}

This is intentional. JSON numbers in JavaScript are IEEE 754 doubles, which lose precision for integers above 2^53 (about 9 quadrillion). While most wallet balances are well below this limit, using strings is a defensive measure that prevents subtle bugs in any client language.

Fee Calculations

Fees are calculated using integer arithmetic with rounding rules:

  1. Calculate the percentage fee: floor(amount * percentageBps / 10000)
  2. Add the flat fee component
  3. Clamp to min/max bounds
  4. The result is always an integer in the smallest currency unit

No floating-point numbers are involved at any step.

Why This Matters

Floating-point arithmetic produces results like:

0.1 + 0.2 = 0.30000000000000004

In a financial system handling thousands of transactions, these tiny errors compound. By using integer arithmetic throughout the stack — from the database (bigint columns) through the application logic to the API wire format (integer or string) — FWallet eliminates this entire class of bugs.