Files
xo-cli/src/utils/rates/base-rates.ts
T
2026-06-01 12:36:55 +02:00

73 lines
2.4 KiB
TypeScript

import { EventEmitter } from "../event-emitter.js";
/**
* Events emitted by our Rates Adapters
*/
export type RatesEventMap = {
rateUpdated: {
numeratorUnitCode: string;
denominatorUnitCode: string;
price: number;
};
};
export abstract class BaseRates<
T extends RatesEventMap = RatesEventMap,
> extends EventEmitter<T> {
/** Starts the given rates adapter so that it will emit events on price updates. */
public abstract start(): Promise<void>;
/** Stops the given rates adapter so that it will stop checking for price updates. */
public abstract stop(): Promise<void>;
/**
* List all available market products (pairs).
* @returns A set of strings in the format "NUMERATOR/DENOMINATOR"
*/
public abstract listPairs(): Promise<Set<string>>;
// TODO: Consider whether we actually want the below.
// Ideally, we will want to replace this with something like the Units class:
// See: https://gitlab.com/GeneralProtocols/xo/stack/-/issues/44
/**
* Format the amount in the target currency to the correct number of decimal places.
*
* @param {number} amount - The amount to format.
* @param {string} targetCurrency - The target currency.
*
* @returns The formatted amount.
*/
public formatCurrency(amount: number, targetCurrency: string): string {
const normalizedCurrency = targetCurrency.toUpperCase();
const minimumFractionDigitsMap: { [currency: string]: number } = {
AUD: 2,
BCH: 8,
USD: 2,
};
const minimumFractionDigits =
minimumFractionDigitsMap[normalizedCurrency] ?? 2;
const maximumFractionDigits = Math.max(minimumFractionDigits, 8);
try {
const formatter = new Intl.NumberFormat("en-US", {
style: "currency",
currency: normalizedCurrency,
currencyDisplay: "narrowSymbol",
minimumFractionDigits,
maximumFractionDigits,
});
return formatter.format(amount);
} catch {
// Some numerator symbols from oracle pairs (e.g. DOGE/BCH) are not ISO-4217
// fiat currency codes, so Intl currency formatting will throw a RangeError.
// In that case we still return a human-readable formatted value.
const numericFormatter = new Intl.NumberFormat("en-US", {
minimumFractionDigits,
maximumFractionDigits,
});
return `${numericFormatter.format(amount)} ${normalizedCurrency}`;
}
}
}