refactor: rename grossSats → principalSats for terminology consistency

"Gross" was operator-vs-customer ambiguous (cash-out: customer's gross
payment = principal + commission, not the variable's value). atm-tui
already settled on "principal" for the same quantity (bitspire/atm-tui
src/db.zig:166-171, src/main.zig:98,716), and #44's Payment.extra
proposal will surface it as `principal_sats` on the kind-21000 wire.
Aligning the internal name removes one translation step across DB →
TUI → state machine → wire envelope.

Pure mechanical rename — no behavioral change. Also rewrites the
computeFeeSats JSDoc to drop the "gross"/"net" framing and document
the principalSats / on-wire satsAmount relationship explicitly.

Refs aiolabs/lamassu-next#44

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-05-14 15:24:53 +02:00
commit ec14bb16c6
3 changed files with 25 additions and 22 deletions

View file

@ -28,13 +28,16 @@ const isElectron = typeof window !== 'undefined' && window.electronAPI !== undef
/** /**
* Compute fee in sats from context. * Compute fee in sats from context.
* Cash-in: customer gets net (gross - fee). Cash-out: customer pays gross + fee. *
* principalSats = market-rate sats for the fiat amount (fiat × exchangeRate, no commission).
* Cash-in: on-wire satsAmount = principalSats - feeSats (customer receives less than principal)
* Cash-out: on-wire satsAmount = principalSats + feeSats (customer pays more than principal)
*/ */
function computeFeeSats(ctx: ATMContext, isCashIn: boolean): number { function computeFeeSats(ctx: ATMContext, isCashIn: boolean): number {
const grossSats = ctx.exchangeRate > 0 ? Math.floor((ctx.fiatCents / 100) * ctx.exchangeRate) : 0 const principalSats = ctx.exchangeRate > 0 ? Math.floor((ctx.fiatCents / 100) * ctx.exchangeRate) : 0
const feeSats = isCashIn const feeSats = isCashIn
? grossSats - ctx.satsAmount // cash-in: customer gets net ? principalSats - ctx.satsAmount // cash-in: customer receives less than principal
: ctx.satsAmount - grossSats // cash-out: customer pays gross + fee : ctx.satsAmount - principalSats // cash-out: customer pays more than principal
return Math.max(0, feeSats) return Math.max(0, feeSats)
} }
@ -850,9 +853,9 @@ export const useAtmStore = defineStore('atm', () => {
// Calculate what the new sats amount would be // Calculate what the new sats amount would be
const newFiatCents = ctx.fiatCents + denomination * 100 const newFiatCents = ctx.fiatCents + denomination * 100
const newFiatUnits = newFiatCents / 100 const newFiatUnits = newFiatCents / 100
const grossSats = Math.floor(newFiatUnits * ctx.exchangeRate) const principalSats = Math.floor(newFiatUnits * ctx.exchangeRate)
const fee = Math.floor(grossSats * ctx.feePercent) const fee = Math.floor(principalSats * ctx.feePercent)
const newSatsAmount = grossSats - fee const newSatsAmount = principalSats - fee
// Check against available balance // Check against available balance
if (newSatsAmount > ctx.availableBalance) { if (newSatsAmount > ctx.availableBalance) {
@ -1106,9 +1109,9 @@ export const useAtmStore = defineStore('atm', () => {
// Calculate if this bill would exceed available balance // Calculate if this bill would exceed available balance
const newFiatCents = ctx.fiatCents + denomination * 100 const newFiatCents = ctx.fiatCents + denomination * 100
const newFiatUnits = newFiatCents / 100 const newFiatUnits = newFiatCents / 100
const grossSats = Math.floor(newFiatUnits * ctx.exchangeRate) const principalSats = Math.floor(newFiatUnits * ctx.exchangeRate)
const fee = Math.floor(grossSats * ctx.feePercent) const fee = Math.floor(principalSats * ctx.feePercent)
const newSatsAmount = grossSats - fee const newSatsAmount = principalSats - fee
if (newSatsAmount > ctx.availableBalance) { if (newSatsAmount > ctx.availableBalance) {
console.log( console.log(

View file

@ -120,9 +120,9 @@ function canAcceptBill(denomination: number): boolean {
if (!ctx) return false if (!ctx) return false
if (ctx.availableBalance <= 0 || ctx.exchangeRate === 0) return true if (ctx.availableBalance <= 0 || ctx.exchangeRate === 0) return true
const newFiatCents = ctx.fiatCents + denomination * 100 const newFiatCents = ctx.fiatCents + denomination * 100
const grossSats = Math.floor((newFiatCents / 100) * ctx.exchangeRate) const principalSats = Math.floor((newFiatCents / 100) * ctx.exchangeRate)
const fee = Math.floor(grossSats * ctx.feePercent) const fee = Math.floor(principalSats * ctx.feePercent)
return grossSats - fee <= ctx.availableBalance return principalSats - fee <= ctx.availableBalance
} }
const balanceLimitReached = computed(() => { const balanceLimitReached = computed(() => {

View file

@ -189,9 +189,9 @@ export function createATMMachine(
satsAmount: ({ context }) => { satsAmount: ({ context }) => {
if (context.exchangeRate === 0) return 0 if (context.exchangeRate === 0) return 0
const fiatDollars = context.fiatCents / 100 const fiatDollars = context.fiatCents / 100
const grossSats = Math.floor(fiatDollars * context.exchangeRate) const principalSats = Math.floor(fiatDollars * context.exchangeRate)
const fee = Math.floor(grossSats * context.feePercent) const fee = Math.floor(principalSats * context.feePercent)
return grossSats - fee return principalSats - fee
}, },
}), }),
calculateDispenseAmounts: assign({ calculateDispenseAmounts: assign({
@ -324,10 +324,10 @@ export function createATMMachine(
satsAmount: ({ context }) => { satsAmount: ({ context }) => {
if (context.exchangeRate === 0) return 0 if (context.exchangeRate === 0) return 0
const fiatDollars = context.fiatCents / 100 const fiatDollars = context.fiatCents / 100
const grossSats = Math.floor(fiatDollars * context.exchangeRate) const principalSats = Math.floor(fiatDollars * context.exchangeRate)
// For cash-out, user pays the sats, so fee is added // For cash-out, user pays the sats, so fee is added
const fee = Math.floor(grossSats * context.feePercent) const fee = Math.floor(principalSats * context.feePercent)
return grossSats + fee return principalSats + fee
}, },
}), }),
calculateDispenseFromSelection: assign({ calculateDispenseFromSelection: assign({
@ -372,9 +372,9 @@ export function createATMMachine(
// cash we can't cover with sats // cash we can't cover with sats
if (context.availableBalance <= 0 || context.exchangeRate === 0) return false if (context.availableBalance <= 0 || context.exchangeRate === 0) return false
const newFiatCents = context.fiatCents + event.denomination * 100 const newFiatCents = context.fiatCents + event.denomination * 100
const grossSats = Math.floor((newFiatCents / 100) * context.exchangeRate) const principalSats = Math.floor((newFiatCents / 100) * context.exchangeRate)
const fee = Math.floor(grossSats * context.feePercent) const fee = Math.floor(principalSats * context.feePercent)
return grossSats - fee <= context.availableBalance return principalSats - fee <= context.availableBalance
}, },
// Cash-out guards // Cash-out guards
hasSelectedAmount: ({ context }) => context.cashOutSelection.length > 0, hasSelectedAmount: ({ context }) => context.cashOutSelection.length > 0,