Currency Handling for Inexperienced Devs

Modern fintech and crypto apps handle currency in multiple forms: local fiat (NGN, KES, etc.), stablecoins (USDT, USDC), or volatile crypto assets (BTC, ETH). Mistakes in how you store, convert, or display these values can lead to real financial losses, user confusion, or major accounting errors. This guide covers the fundamentals.


Store Amounts in Smallest Units

Why It Matters

Floating-point arithmetic (like float or double in many languages) can introduce rounding errors. This is especially risky when dealing with money. It’s safer to keep all amounts in integer form, representing the smallest unit.

Examples

If you plan to collaborate with others, consider using a dedicated email or a shared workspace for your dev team.

Bitcoin: 1 BTC = 100,000,000 satoshis

So if a user has 0.001 BTC, store 100,000 sats, not 0.001.

Fiat: 1 NGN can be stored as 100 kobo, 1 USD can be 100 cents.

Pseudocode

This prevents weird decimals like 12.3455999999 from creeping in.


Convert Only at the Edges

Principle

Keep internal logic in a single currency unit. Convert to a display-friendly format (like NGN, USD, or BTC) at the last possible moment.

Examples

If your backend stores NGN in kobo, do calculations in kobo. When you’re about to show a user “₦,1000.00,” then divide by 100 and format.


Rounding Rules and User Display

Rounding

Decide how to round or truncate for user-facing balances. For example, if you do a swap that results in 0.999876 BTC:

For display, you might show 0.9999 BTC

Under the hood, you store the integer satoshi value (99,987,600 sats)

User Display

Label currencies clearly, especially if you handle both fiat and crypto.

For fiat, prefix or suffix with “₦” or “$.”

For crypto, suffix with “BTC” or “USDT.”

Examples

Balance: 50,000 kobo

Display: ₦500.00


Handling exchange

Principle

Keep internal logic in a single currency unit. Convert to a display-friendly format (like NGN, USD, or BTC) at the last possible moment.

Examples

If your backend stores NGN in kobo, do calculations in kobo. When you’re about to show a user “₦,1000.00,” then divide by 100 and format.

Rounding Rules and User Display

Rounding

Decide how to round or truncate for user-facing balances. For example, if you do a swap that results in 0.999876 BTC:

1.

Fetch or lock in an exchange rate at a specific moment (e.g. the user requests a quote).

2.

Store that rate in your records, so you can prove how you derived the final amount.

3.

Apply the rate to the user’s input or your stored amounts in the smallest unit.

4.

Perform integer math if possible (like satoshis → kobo).

5.

If you must do decimal conversion, use a fixed-precision or big decimal library to avoid floating-point errors.

Pseudocode

Use a library like bigdecimal.js or Python’s decimal module to avoid floating inaccuracies.


Different Crypto Chains, Different Multipliers

Why

USDT has many variants (TRC20, ERC20, BEP20, etc.). Some have 6 decimals, some 18 decimals. Always consult the chain specs or your API docs to confirm the correct smallest unit or multiplier.

Examples

On Tron (TRC20), USDT might have 6 decimals (1 USDT = 1,000,000 micropennies).

On Ethereum (ERC20), USDT might also have 6 decimals, but some tokens like USDC can have 6 while others have 18.

Keep chain-based metadata in your code or config.

Watch Out for Fees and Gas

On-chain Fees

If you’re doing a transaction on a blockchain, the user’s final amount received might be reduced by network fees or gas. Communicate these fees clearly and either subtract them from the user’s total or collect them separately.

Lightning or Service Fees

Lightning or additional service fees might apply. Always confirm how these fees are deducted before finalizing a user’s transaction.


Multi-Currency Flows

1.

Single Currency

Easiest path. For instance, store everything in NGN (for a local-only app) or in BTC (for a pure-BTC app).

2.

Multi-Currency

If you’re bridging stablecoins, BTC, and fiat:

Keep each currency’s balance in separate fields or columns.

Convert only when necessary.

Use references to tie multiple conversions into one transaction record.

3.

Cross-Border Remittance

Check local regulators on which currency to display at each stage. You might show an estimate in the user’s home currency but store the final conversion in the recipient’s currency.


Example Flow: Accept BTC, Pay in NGN

1.

Get user’s BTC amount in satoshis.

2.

Use an exchange rate to find NGN kobo equivalent.

3.

Add fees if any.

4.

Store the result in your DB as an integer of kobo.

5.

Display “₦2000.00” to the user.

This avoids floating conversion issues and ensures each step is trackable.


Thorough Testing

1.

Test tiny amounts like 1 sat or 1 kobo.

2.

Test large amounts near your max limit.

3.

Test rounding edge cases (e.g. 0.9999 crossing into 1.0000)

4.

Test different locales for currency formatting if you have a diverse user base.


Library and Tool Recommendations

1.

Big.js or decimal.js for JavaScript

2.

decimal or in Python

3.

BigDecimal in Java/Kotlin

4.

Always store as integers where feasible, especially for ledger amounts


Summary of Best Practices

1.

Store amounts in smallest integer unit to avoid floating bugs

2.

Convert to user-friendly format only at display time

3.

Lock and record your exchange rates for each conversion

4.

Be mindful of different decimals for stablecoins across chains

5.

Include fees in your math logic

6.

Test extreme amounts and rounding scenarios

A little planning on currency handling saves you major headaches in production. It ensures your users see consistent numbers, your audits match your records, and you maintain trust by never “losing” or “gaining” money due to floating-point errors.

Did you find this page useful?