mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 17:10:56 +00:00
81 lines
2.4 KiB
TypeScript
81 lines
2.4 KiB
TypeScript
import { Inject, Injectable } from "@nestjs/common";
|
|
|
|
import { CbeExchangeProvider, CbeProviderStatus } from "./cbe.provider";
|
|
import { EXCHANGE_OPTIONS, ExchangeOptions } from "./exchange.options";
|
|
import { CurrencyCode } from "./exchange.types";
|
|
|
|
/**
|
|
* Currency exchange service. Resolves the rate between any supported currency
|
|
* pair and converts amounts, backed by a rate provider (currently CBE).
|
|
*
|
|
* Resolution order for `getRate(from, to)`:
|
|
* 1. `from === to` → `1`.
|
|
* 2. Provider supplies the pair directly (e.g. CBE → USD→ETB).
|
|
* 3. Provider supplies the inverse → return `1 / inverse` (e.g. ETB→USD).
|
|
*
|
|
* Configure via {@link ExchangeModule.forRoot} / `forRootAsync`.
|
|
*/
|
|
@Injectable()
|
|
export class ExchangeService {
|
|
private readonly provider: CbeExchangeProvider;
|
|
|
|
constructor(@Inject(EXCHANGE_OPTIONS) options: ExchangeOptions) {
|
|
this.provider = new CbeExchangeProvider(options);
|
|
}
|
|
|
|
/**
|
|
* Returns the rate to convert 1 unit of `from` into `to`
|
|
* (i.e. `amountInTo = amountInFrom * getRate(from, to)`).
|
|
*/
|
|
async getRate(from: CurrencyCode, to: CurrencyCode): Promise<number> {
|
|
if (from === to) {
|
|
return 1;
|
|
}
|
|
|
|
const direct = await this.provider.getBaseRate({ from, to });
|
|
if (direct !== null) {
|
|
return direct;
|
|
}
|
|
|
|
const inverse = await this.provider.getBaseRate({ from: to, to: from });
|
|
if (inverse !== null && inverse > 0) {
|
|
return 1 / inverse;
|
|
}
|
|
|
|
throw new Error(
|
|
`No exchange rate available for ${from}→${to} from provider ${this.provider.name}`,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Health of the underlying rate feed — what was served last and whether it
|
|
* is currently failing. For operator-facing status displays.
|
|
*/
|
|
getProviderStatus(): CbeProviderStatus {
|
|
return this.provider.getStatus();
|
|
}
|
|
|
|
/** Converts `amount` from one currency to another using {@link getRate}. */
|
|
async convert(
|
|
amount: number,
|
|
from: CurrencyCode,
|
|
to: CurrencyCode,
|
|
): Promise<number> {
|
|
const rate = await this.getRate(from, to);
|
|
return amount * rate;
|
|
}
|
|
|
|
/**
|
|
* Convenience alias for `getRate('USD', 'ETB')`.
|
|
* @deprecated Prefer {@link getRate}; kept for existing callers.
|
|
*/
|
|
getUsdToEtbRate(): Promise<number> {
|
|
return this.getRate("USD", "ETB");
|
|
}
|
|
|
|
/** Convenience alias for `getRate('ETB', 'USD')`. */
|
|
getEtbToUsdRate(): Promise<number> {
|
|
return this.getRate("ETB", "USD");
|
|
}
|
|
}
|