exchange
Converts money from one currency to another using the provided exchange rate. Maintains precision by using bigint arithmetic.
Implementation
View Source Code
ts
import type { Money } from './types';
/**
* Exchange rate for currency conversion.
*/
export type ExchangeRate = {
from: string; // Source currency code
to: string; // Target currency code
rate: number; // Exchange rate multiplier
};
/**
* Converts money from one currency to another using the provided exchange rate.
* Maintains precision by using bigint arithmetic.
*
* @example
* ```ts
* const usd = { amount: 100000n, currency: 'USD' }; // $1,000.00
* const rate = { from: 'USD', to: 'EUR', rate: 0.85 };
*
* exchange(usd, rate);
* // { amount: 85000n, currency: 'EUR' } // €850.00
* ```
*
* @param money - Money to convert
* @param rate - Exchange rate information
* @returns Converted money in target currency
* @throws {Error} If source currency doesn't match rate.from
*/
export function exchange(money: Money, rate: ExchangeRate): Money {
if (money.currency !== rate.from) {
throw new Error(`Currency mismatch: expected ${rate.from}, got ${money.currency}`);
}
// Convert rate to avoid floating point issues
// Multiply by 1000000 for precision, then divide back
const rateBigInt = BigInt(Math.round(rate.rate * 1000000));
const convertedAmount = (money.amount * rateBigInt) / 1000000n;
return {
amount: convertedAmount,
currency: rate.to,
};
}Features
- Precision-Safe: Uses bigint arithmetic to avoid floating-point errors
- Currency Validation: Ensures source currency matches exchange rate
- Type-Safe: Uses Money and ExchangeRate types
- Flexible Rates: Accepts any exchange rate multiplier
- Isomorphic: Works in both Browser and Node.js
API
Type Definitions
ts
/**
* Represents a monetary amount with currency.
* Amount is stored as bigint (minor units/cents) for precision.
*/
export type Money = {
readonly amount: bigint; // Amount in minor units (e.g., cents for USD)
readonly currency: string; // ISO 4217 currency code (e.g., 'USD', 'EUR')
};ts
function exchange(money: Money, rate: ExchangeRate): Money;Parameters
money: Money object to convertamount: Amount in minor units (cents) as bigintcurrency: ISO 4217 source currency code
rate: Exchange rate informationfrom: Source currency code (must match money.currency)to: Target currency coderate: Exchange rate multiplier
Returns
- New Money object in target currency
Throws
Error: If source currency doesn't match rate.from
Examples
Basic Currency Conversion
ts
import { exchange } from '@vielzeug/toolkit';
const usd = { amount: 100000n, currency: 'USD' }; // $1,000.00
const rate = { from: 'USD', to: 'EUR', rate: 0.85 };
const eur = exchange(usd, rate);
// { amount: 85000n, currency: 'EUR' } // €850.00Reverse Conversion
ts
import { exchange } from '@vielzeug/toolkit';
const eur = { amount: 85000n, currency: 'EUR' }; // €850.00
const rate = { from: 'EUR', to: 'USD', rate: 1.18 };
const usd = exchange(eur, rate);
// { amount: 100300n, currency: 'USD' } // ~$1,003.00Real-World Example: International Purchase
ts
import { exchange, currency } from '@vielzeug/toolkit';
// Product price in USD
const productPrice = { amount: 49999n, currency: 'USD' }; // $499.99
// Current exchange rate USD -> EUR
const usdToEur = { from: 'USD', to: 'EUR', rate: 0.92 };
// Convert to EUR for European customer
const priceInEur = exchange(productPrice, usdToEur);
// { amount: 45999n, currency: 'EUR' }
console.log(`Price: ${currency(priceInEur, { locale: 'de-DE' })}`);
// Price: 459,99 €Multi-Currency Conversion
ts
import { exchange } from '@vielzeug/toolkit';
const usd = { amount: 100000n, currency: 'USD' }; // $1,000.00
// Convert to multiple currencies
const rates = [
{ from: 'USD', to: 'EUR', rate: 0.85 },
{ from: 'USD', to: 'GBP', rate: 0.73 },
{ from: 'USD', to: 'JPY', rate: 110.0 },
];
const conversions = rates.map((rate) => ({
currency: rate.to,
amount: exchange(usd, rate),
}));
// EUR: { amount: 85000n, currency: 'EUR' }
// GBP: { amount: 73000n, currency: 'GBP' }
// JPY: { amount: 11000000n, currency: 'JPY' }High Exchange Rate (to JPY)
ts
import { exchange } from '@vielzeug/toolkit';
const usd = { amount: 10000n, currency: 'USD' }; // $100.00
const rate = { from: 'USD', to: 'JPY', rate: 110.5 };
const jpy = exchange(usd, rate);
// { amount: 1105000n, currency: 'JPY' } // ¥11,050Low Exchange Rate (from JPY)
ts
import { exchange } from '@vielzeug/toolkit';
const jpy = { amount: 1105000n, currency: 'JPY' }; // ¥11,050
const rate = { from: 'JPY', to: 'USD', rate: 0.00905 };
const usd = exchange(jpy, rate);
// { amount: 10000n, currency: 'USD' } // ~$100.00Dynamic Exchange Rates
ts
import { exchange } from '@vielzeug/toolkit';
// Fetch current exchange rate from API
async function convertCurrency(money: Money, targetCurrency: string) {
// Simulated API call
const apiRate = await fetchExchangeRate(money.currency, targetCurrency);
const rate = {
from: money.currency,
to: targetCurrency,
rate: apiRate,
};
return exchange(money, rate);
}
// Usage
const usd = { amount: 250000n, currency: 'USD' };
const gbp = await convertCurrency(usd, 'GBP');Currency Validation Error
ts
import { exchange } from '@vielzeug/toolkit';
const eur = { amount: 100000n, currency: 'EUR' };
const wrongRate = { from: 'USD', to: 'GBP', rate: 0.73 };
try {
exchange(eur, wrongRate);
} catch (error) {
console.error(error);
// Error: Currency mismatch: expected USD, got EUR
}Chain Conversions
ts
import { exchange } from '@vielzeug/toolkit';
// USD -> EUR -> GBP
const usd = { amount: 100000n, currency: 'USD' };
const usdToEur = { from: 'USD', to: 'EUR', rate: 0.85 };
const eur = exchange(usd, usdToEur);
// { amount: 85000n, currency: 'EUR' }
const eurToGbp = { from: 'EUR', to: 'GBP', rate: 0.86 };
const gbp = exchange(eur, eurToGbp);
// { amount: 73100n, currency: 'GBP' }Implementation Notes
- Precision: Uses bigint multiplication/division to maintain precision
- Rate Multiplier: Rate of 0.85 means 1 unit of source = 0.85 units of target
- Minor Units: Both source and target amounts are in minor units (cents)
- Rounding: Uses integer division (truncates), may lose fractional cents
- Rate Source: You must provide exchange rates (from API, database, etc.)
- Currency Validation: Always validates that source currency matches rate.from
- Negative Amounts: Handles negative amounts correctly
- Precision Factor: Internally uses 6 decimal places for rate precision