Hello from MCP server

List Files | Just Commands | Repo | Logs

← back |
import type { CurrenciesRecord } from "@/pocketbase-types";
import { getDb } from "@/dataAccess/getDb";

export interface CurrencyRate {
  baseCurrency: string;
  quoteCurrency: string;
  rate: number;
  name?: string;
  created?: string;
}

export interface CurrenciesData {
  currencies: CurrenciesRecord[];
  rates: CurrencyRate[];
}

/**
 * Convert a value from one currency to another with maximum precision.
 * No rounding is applied - precision is maintained throughout.
 *
 * @param rates - Array of currency rates
 * @param from - Source currency code (e.g., "XAG")
 * @param to - Target currency code (e.g., "USD")
 * @param value - Value to convert
 * @returns Converted value with full precision
 */
export function convert(
  rates: CurrencyRate[],
  from: string,
  to: string,
  value: number,
): number {
  // Same currency - no conversion needed
  if (from === to) {
    return value;
  }

  // Find direct rate from -> to
  const directRate = rates.find(
    (r) => r.baseCurrency === from && r.quoteCurrency === to,
  );
  if (directRate) {
    return value * directRate.rate;
  }

  // Find inverse rate to -> from and invert it
  const inverseRate = rates.find(
    (r) => r.baseCurrency === to && r.quoteCurrency === from,
  );
  if (inverseRate && inverseRate.rate !== 0) {
    return value / inverseRate.rate;
  }

  // No rate found - return original value
  console.warn(`No exchange rate found for ${from} -> ${to}`);
  return value;
}

export async function loadCurrencies(): Promise<CurrenciesData> {
  const db = await getDb();

  const [currencies, rates] = await Promise.all([
    db.currencies.getAll(),
    db.currencies.getRates(),
  ]);

  // Parse rate as number (may be stored as string)
  const parsedRates: CurrencyRate[] = (rates || []).map((r: any) => ({
    baseCurrency: r.baseCurrency,
    quoteCurrency: r.quoteCurrency,
    rate: typeof r.rate === "string" ? parseFloat(r.rate) : r.rate,
    name: r.name || undefined,
    created: r.created || undefined,
  }));

  return {
    currencies: currencies || [],
    rates: parsedRates,
  };
}

export interface CurrencyPrefs {
  baseCurrency: string;
  targetCurrency: string;
  exchangeRate: number;
  symbol: string;
}

/**
 * Store currency preferences to the local userPrefs table
 */
export async function storeCurrency(prefs: CurrencyPrefs): Promise<void> {
  const db = await getDb();

  const stmt = `
    INSERT INTO userPrefs (key, value) VALUES (?, ?)
    ON CONFLICT(key) DO UPDATE SET value = excluded.value
  `;

  await db.dbConn.run(stmt, ["currency.baseCurrency", prefs.baseCurrency]);
  await db.dbConn.run(stmt, ["currency.targetCurrency", prefs.targetCurrency]);
  await db.dbConn.run(stmt, ["currency.exchangeRate", prefs.exchangeRate.toString()]);
  await db.dbConn.run(stmt, ["currency.symbol", prefs.symbol]);

  // Persist to disk
  await db.saveDb();
}

/**
 * Load currency preferences from the local userPrefs table
 */
export async function loadCurrencyPrefs(): Promise<CurrencyPrefs | null> {
  const db = await getDb();

  const result = await db.dbConn.query(
    "SELECT key, value FROM userPrefs WHERE key LIKE 'currency.%'"
  );

  if (!result.values || result.values.length === 0) {
    return null;
  }

  const prefs: Record<string, string> = {};
  for (const row of result.values) {
    const key = row.key.replace("currency.", "");
    prefs[key] = row.value;
  }

  if (!prefs.baseCurrency || !prefs.targetCurrency) {
    return null;
  }

  return {
    baseCurrency: prefs.baseCurrency,
    targetCurrency: prefs.targetCurrency,
    exchangeRate: parseFloat(prefs.exchangeRate) || 0,
    symbol: prefs.symbol || "",
  };
}

export interface ConvertedValue {
  value: number;
  formatted: string;
  symbol: string;
  targetCurrency: string;
}

/**
 * Convert a value from base currency (XAG) to the user's preferred currency
 * using the saved currency preferences.
 *
 * @param valueInBaseCurrency - The value in base currency (XAG)
 * @returns Converted value with formatting, or null if no prefs saved
 */
export async function convertToPrefs(valueInBaseCurrency: number): Promise<ConvertedValue | null> {
  const prefs = await loadCurrencyPrefs();

  if (!prefs || !prefs.exchangeRate) {
    return null;
  }

  const convertedValue = valueInBaseCurrency * prefs.exchangeRate;

  return {
    value: convertedValue,
    formatted: `${prefs.symbol}${convertedValue.toFixed(2)}`,
    symbol: prefs.symbol,
    targetCurrency: prefs.targetCurrency,
  };
}

/**
 * Convert multiple values from base currency to user's preferred currency
 *
 * @param values - Record of values in base currency (XAG)
 * @returns Record of converted values, or null if no prefs saved
 */
export async function convertManyToPrefs(
  values: Record<string, number>
): Promise<Record<string, ConvertedValue> | null> {
  const prefs = await loadCurrencyPrefs();

  if (!prefs || !prefs.exchangeRate) {
    return null;
  }

  const result: Record<string, ConvertedValue> = {};

  for (const [key, value] of Object.entries(values)) {
    const convertedValue = value * prefs.exchangeRate;
    result[key] = {
      value: convertedValue,
      formatted: `${prefs.symbol}${convertedValue.toFixed(2)}`,
      symbol: prefs.symbol,
      targetCurrency: prefs.targetCurrency,
    };
  }

  return result;
}

/**
 * Convert a value from user's preferred currency back to base currency (XAG).
 * This is the inverse of convertToPrefs.
 *
 * @param valueInPreferredCurrency - The value in user's preferred currency
 * @returns Value in base currency (XAG), or null if no prefs saved
 */
export async function convertFromPrefs(valueInPreferredCurrency: number): Promise<number | null> {
  const prefs = await loadCurrencyPrefs();
  console.log('[convertFromPrefs] prefs:', prefs, 'value:', valueInPreferredCurrency);

  if (!prefs || !prefs.exchangeRate) {
    console.log('[convertFromPrefs] No prefs or exchangeRate, returning null');
    return null;
  }

  // Divide by exchange rate to convert back to base currency
  const result = valueInPreferredCurrency / prefs.exchangeRate;
  console.log('[convertFromPrefs] result:', result);
  return result;
}