Files
brazil-swift-ops/packages/utils/src/currency.ts
defiQUG 8c771da399 Initial implementation: Brazil SWIFT Operations Platform
- Complete monorepo structure with pnpm workspaces and Turborepo
- All packages implemented: types, utils, rules-engine, iso20022, treasury, risk-models, audit
- React web application with TypeScript and Tailwind CSS
- Full Brazil regulatory compliance (BCB requirements)
- ISO 20022 message support (pacs.008, pacs.009, pain.001)
- Treasury and subledger management
- Risk, capital, and liquidity stress allocation
- Audit logging and BCB reporting
- E&O +10% uplift implementation
2026-01-23 14:51:10 -08:00

131 lines
3.5 KiB
TypeScript

/**
* Currency conversion and USD equivalent calculation utilities
*/
import Decimal from 'decimal.js';
export interface ExchangeRate {
fromCurrency: string;
toCurrency: string;
rate: number;
effectiveDate: Date;
source?: string;
}
export interface CurrencyConverter {
convert(amount: number, fromCurrency: string, toCurrency: string, date?: Date): number;
getUSDEquivalent(amount: number, currency: string, date?: Date): number;
getRate(fromCurrency: string, toCurrency: string, date?: Date): number | null;
}
/**
* Simple in-memory currency converter with configurable rates
* In production, this would integrate with a real-time FX rate service
*/
export class SimpleCurrencyConverter implements CurrencyConverter {
private rates: Map<string, ExchangeRate> = new Map();
private defaultUSDRates: Record<string, number> = {
USD: 1.0,
BRL: 0.2,
EUR: 1.1,
GBP: 1.27,
};
constructor(initialRates?: ExchangeRate[]) {
if (initialRates) {
initialRates.forEach((rate) => this.addRate(rate));
}
this.initializeDefaultRates();
}
private initializeDefaultRates(): void {
const now = new Date();
Object.entries(this.defaultUSDRates).forEach(([currency, rate]) => {
if (currency !== 'USD') {
this.addRate({
fromCurrency: currency,
toCurrency: 'USD',
rate,
effectiveDate: now,
source: 'default',
});
}
});
}
addRate(rate: ExchangeRate): void {
const key = this.getRateKey(rate.fromCurrency, rate.toCurrency);
this.rates.set(key, rate);
const inverseKey = this.getRateKey(rate.toCurrency, rate.fromCurrency);
this.rates.set(inverseKey, {
...rate,
fromCurrency: rate.toCurrency,
toCurrency: rate.fromCurrency,
rate: 1 / rate.rate,
});
}
private getRateKey(fromCurrency: string, toCurrency: string): string {
return `${fromCurrency}:${toCurrency}`;
}
getRate(fromCurrency: string, toCurrency: string, date?: Date): number | null {
if (fromCurrency === toCurrency) {
return 1.0;
}
const key = this.getRateKey(fromCurrency, toCurrency);
const rate = this.rates.get(key);
if (!rate) {
if (fromCurrency !== 'USD' && toCurrency !== 'USD') {
const fromToUSD = this.getRate(fromCurrency, 'USD', date);
const usdToTo = this.getRate('USD', toCurrency, date);
if (fromToUSD && usdToTo) {
return fromToUSD * usdToTo;
}
}
return null;
}
return rate.rate;
}
convert(amount: number, fromCurrency: string, toCurrency: string, date?: Date): number {
if (fromCurrency === toCurrency) {
return amount;
}
const rate = this.getRate(fromCurrency, toCurrency, date);
if (rate === null) {
throw new Error(
`No exchange rate available for ${fromCurrency} to ${toCurrency}`
);
}
const amountDecimal = new Decimal(amount);
const rateDecimal = new Decimal(rate);
return amountDecimal.mul(rateDecimal).toNumber();
}
getUSDEquivalent(amount: number, currency: string, date?: Date): number {
if (currency === 'USD') {
return amount;
}
return this.convert(amount, currency, 'USD', date);
}
}
let defaultConverter: CurrencyConverter | null = null;
export function getDefaultConverter(): CurrencyConverter {
if (!defaultConverter) {
defaultConverter = new SimpleCurrencyConverter();
}
return defaultConverter;
}
export function setDefaultConverter(converter: CurrencyConverter): void {
defaultConverter = converter;
}