Balances
Understand how Infrarails represents and maintains financial values.
Balances are a central part of the Infrarails accounting model.
Each account maintains financial amounts in integer minor units, allowing applications to work with currency values without relying on floating-point storage.
Balance fields
The core account model includes two balance fields.
| Field | Description |
|---|---|
available_balance | Available balance in integer minor units |
pending_balance | Pending balance in integer minor units |
Both fields must be interpreted using the account's currency and currency exponent.
Minor units
Infrarails stores monetary amounts as integers.
For currencies with an exponent of 2, the stored amount represents hundredths of the currency unit.
For example:
| Stored value | EUR amount |
|---|---|
| 1 | €0.01 |
| 100 | €1.00 |
| 1699 | €16.99 |
| 10000 | €100.00 |
| 125050 | €1,250.50 |
| 1000000 | €10,000.00 |
Currency exponent
The currency exponent determines the relationship between stored integer values and their human-readable representation.
The general formula is:
Display amount = Stored amount / (10 ^ currency_exponent)
For an exponent of 2:
Stored amount: 1699
Currency exponent: 2
1699 / 100 = 16.99
The result is EUR 16.99 when the account currency is EUR.
Applications should use the exponent provided by the account rather than hardcoding two decimal places for every currency.
Available balance
The available balance represents the account's available financial position according to the ledger's accounting rules.
For example, consider an account with:
{
"currency": "EUR",
"currency_exponent": 2,
"available_balance": 250000
}
Its available balance is EUR 2,500.00.
Pending balance
The pending balance is maintained separately from the available balance.
For example:
{
"currency": "EUR",
"currency_exponent": 2,
"available_balance": 250000,
"pending_balance": 50000
}
This represents:
- Available balance: EUR 2,500.00
- Pending balance: EUR 500.00
These values should not automatically be added together or interpreted as a withdrawable total. Their precise meaning depends on the ledger's transaction posting rules.
Balance changes
Financial movements should be performed through supported ledger transaction operations.
For example, consider two EUR accounts:
| Account | Initial available balance |
|---|---|
| Account A | €1,000.00 |
| Account B | €250.00 |
A completed transfer of EUR 100.00 from Account A to Account B would produce:
| Account | Before | After |
|---|---|---|
| Account A | €1,000.00 | €900.00 |
| Account B | €250.00 | €350.00 |
This example assumes no additional fees, holds, or other adjustments.
Precision and arithmetic
Avoid floating-point arithmetic for financial values.
For example, the following calculation may introduce precision issues:
const total = 0.1 + 0.2;
Instead, perform monetary calculations using integer minor units:
const amountA = 10;
const amountB = 20;
const totalMinorUnits = amountA + amountB;
// 30 minor units = EUR 0.30
For values exceeding JavaScript's safe integer range, use an appropriate arbitrary-precision representation and follow the API's numeric serialization requirements.
Displaying balances
The following JavaScript helper formats safe integer minor-unit values using an account's currency exponent.
function formatBalance(amount, currency, exponent) {
if (!Number.isSafeInteger(amount)) {
throw new Error("Amount must be a safe integer");
}
if (!Number.isInteger(exponent) || exponent < 0 || exponent > 20) {
throw new Error("Invalid currency exponent");
}
const negative = amount < 0;
const absolute = BigInt(amount);
const magnitude = negative ? -absolute : absolute;
const divisor = 10n ** BigInt(exponent);
const whole = magnitude / divisor;
const fraction = magnitude % divisor;
const formatted = exponent === 0
? whole.toString()
: `${whole}.${fraction.toString().padStart(exponent, "0")}`;
return `${negative ? "-" : ""}${formatted} ${currency}`;
}
// Example
formatBalance(1699, "EUR", 2);
// "16.99 EUR"
This helper is illustrative. Applications should also use the currency's appropriate locale formatting rules for user-facing displays.
Balance consistency
Applications should treat the ledger as the authoritative source for account balances.
Avoid maintaining independent financial totals without reconciliation against the ledger.
When displaying cached balances, consider the possibility that new transactions have been processed since the last synchronization.
Best practices
- Store and transmit monetary values using the API's documented numeric representation.
- Respect each account's currency exponent.
- Avoid floating-point financial calculations.
- Do not update ledger balances directly.
- Distinguish available and pending balances.
- Validate account currency compatibility.
- Reconcile derived financial reports against authoritative ledger records.
- Use idempotency for eligible financial operations.
Next steps
Continue with Transactions to understand how financial operations affect accounts and balances.
Updated about 1 hour ago