73 lines
2.4 KiB
TypeScript
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}`;
|
|
}
|
|
}
|
|
}
|