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
- All amounts are stored as
bigintin the database, in the smallest unit of the currency. - No floating-point arithmetic on money. Ever. All calculations use integer math.
- API responses return amounts as strings to avoid JSON number precision issues (JavaScript’s
Numbertype loses precision above 2^53).
Currency Table
FWallet supports these currencies, each with a defined number of decimal places:
| Currency | Code | Decimals | Multiplier | Example: “10,000” in display |
|---|---|---|---|---|
| Ugandan Shilling | UGX | 0 | 1 | 10000 |
| Kenyan Shilling | KES | 2 | 100 | 1000000 |
| Tanzanian Shilling | TSH | 0 | 1 | 10000 |
| US Dollar | USD | 2 | 100 | 1000000 |
| Chinese Yuan | CNY | 2 | 100 | 1000000 |
| British Pound | GBP | 2 | 100 | 1000000 |
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^decimalsExamples:
- 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^decimalsExamples:
500000UGX -> 500,000 UGX (/ 1)25050USD -> $250.50 (/ 100)100000KES -> 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:
- Calculate the percentage fee:
floor(amount * percentageBps / 10000) - Add the flat fee component
- Clamp to min/max bounds
- 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.30000000000000004In 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.