Files
actual-helpers/sync-bitcoin.js
T
2025-05-06 09:56:07 -05:00

74 lines
2.2 KiB
JavaScript

const { closeBudget, openBudget, getTransactions, getAccountNote, getAccountBalance, getTagValue, ensurePayee } = require('./utils');
const api = require('@actual-app/api');
function getValueAtPath(obj, path) {
const keys = path.split('.').filter(Boolean);
return keys.reduce((acc, key) => {
const match = key.match(/^([^\[\]]+)(\[(\d+)\])?$/);
if (match) {
const property = match[1];
const index = match[3];
acc = acc[property];
if (index !== undefined) {
acc = acc[parseInt(index, 10)];
}
} else {
acc = acc[key];
}
return acc;
}, obj);
}
async function getBitcoinPrice() {
const url = process.env.BITCOIN_PRICE_URL || "https://api.kraken.com/0/public/Ticker?pair=xbtusd"
const path = process.env.BITCOIN_PRICE_JSON_PATH || "result.XXBTZUSD.c[0]"
try {
response = await fetch(url);
const json = await response.json();
return getValueAtPath(json, path);
} catch (error) {
return undefined;
}
}
(async () => {
const bitcoinPrice = await getBitcoinPrice();
if (!bitcoinPrice) {
throw new Error("Unable to retrieve Bitcoin price. Check your BITCOIN_PRICE_URL and BITCOIN_PRICE_JSON_PATH environment variables");
}
await openBudget();
const payeeId = await ensurePayee(process.env.BITCOIN_PAYEE_NAME || 'Bitcoin Price Change');
const accounts = await api.getAccounts();
for (const account of accounts) {
if (account.closed) {
continue;
}
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() + 1);
const note = await getAccountNote(account, cutoffDate);
const btc_amount = parseFloat(getTagValue(note, 'BTC', 0.0));
if (!btc_amount) {
continue;
}
const currentBalance = await getAccountBalance(account);
const targetBalance = Math.round(bitcoinPrice * btc_amount * 100);
const diff = targetBalance - currentBalance;
if (diff != 0) {
await api.importTransactions(account.id, [{
date: new Date(),
payee: payeeId,
amount: diff,
cleared: true,
reconciled: true,
notes: "Updated Bitcoin Price",
}])
}
}
await closeBudget();
})();