Hello from MCP server
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;
}