feat(machine): persist exchange rate and currency in transactions

Add exchange_rate (sats per fiat unit) and currency columns to the
transactions table so transaction economics can be audited after the
fact. Includes schema migration v2 (fee columns) and v3 (rate/currency),
updated IPC types, and atm-transactions CLI output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-03-10 01:30:18 -04:00
commit 310d0edb99
5 changed files with 65 additions and 4 deletions

View file

@ -269,11 +269,22 @@ export const useAtmStore = defineStore('atm', () => {
? buildBillsFromInserted(ctx.billsInserted)
: ctx.dispenseAmounts
// Compute fee in sats from context
const grossSats =
ctx.exchangeRate > 0 ? Math.floor((ctx.fiatCents / 100) * ctx.exchangeRate) : 0
const feeSats = isCashInTx
? grossSats - ctx.satsAmount // cash-in: customer gets net (gross - fee)
: ctx.satsAmount - grossSats // cash-out: customer pays gross + fee
persistTransaction({
txid: ctx.txid,
type: isCashInTx ? 'cash_in' : 'cash_out',
fiatCents: ctx.fiatCents,
sats: ctx.satsAmount,
feeSats: Math.max(0, feeSats),
feePercent: ctx.feePercent,
exchangeRate: ctx.exchangeRate,
currency: ctx.currency,
bills,
})
}

View file

@ -40,6 +40,10 @@ declare global {
type: 'cash_in' | 'cash_out'
fiatCents: number
sats: number
feeSats: number
feePercent: number
exchangeRate: number
currency: string
bills: { denomination: number; count: number }[]
}) => Promise<void>
emptyCashbox: () => Promise<void>

View file

@ -18,6 +18,10 @@ export interface TransactionRecord {
type: 'cash_in' | 'cash_out'
fiatCents: number
sats: number
feeSats: number
feePercent: number
exchangeRate: number
currency: string
bills: { denomination: number; count: number }[]
}