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 { /** Starts the given rates adapter so that it will emit events on price updates. */ public abstract start(): Promise; /** Stops the given rates adapter so that it will stop checking for price updates. */ public abstract stop(): Promise; /** * List all available market products (pairs). * @returns A set of strings in the format "NUMERATOR/DENOMINATOR" */ public abstract listPairs(): Promise>; // 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}`; } } }