fix(state-machine): reject bills when available balance is unknown
Previously, if getAvailableBalance returned 0 or exchange rate was missing, all bills were accepted — risking cash-in exceeding the ATM's sats balance. Now rejects bills in that case to protect customers from losing cash. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8d7e241020
commit
454154e528
2 changed files with 4 additions and 1 deletions
|
|
@ -15,6 +15,7 @@ describe('ATM State Machine', () => {
|
||||||
dispensed: true,
|
dispensed: true,
|
||||||
} satisfies DispenseCashResult),
|
} satisfies DispenseCashResult),
|
||||||
getExchangeRate: vi.fn().mockResolvedValue(2500), // 2500 sats per USD
|
getExchangeRate: vi.fn().mockResolvedValue(2500), // 2500 sats per USD
|
||||||
|
getAvailableBalance: vi.fn().mockResolvedValue(1_000_000), // 1M sats available
|
||||||
// noffer cash-out services (legacy)
|
// noffer cash-out services (legacy)
|
||||||
generateNoffer: vi.fn().mockResolvedValue('noffer1atmtest'),
|
generateNoffer: vi.fn().mockResolvedValue('noffer1atmtest'),
|
||||||
sendOfferResponse: vi.fn().mockResolvedValue(undefined),
|
sendOfferResponse: vi.fn().mockResolvedValue(undefined),
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,9 @@ export function createATMMachine(
|
||||||
hasOfferRequest: ({ context }) => context.pendingOfferRequest !== null,
|
hasOfferRequest: ({ context }) => context.pendingOfferRequest !== null,
|
||||||
billWithinBalance: ({ context, event }) => {
|
billWithinBalance: ({ context, event }) => {
|
||||||
if (event.type !== 'BILL_INSERTED') return false
|
if (event.type !== 'BILL_INSERTED') return false
|
||||||
if (context.availableBalance <= 0 || context.exchangeRate === 0) return true
|
// Reject bills if balance or rate is unknown — don't risk accepting
|
||||||
|
// cash we can't cover with sats
|
||||||
|
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 grossSats = Math.floor((newFiatCents / 100) * context.exchangeRate)
|
||||||
const fee = Math.floor(grossSats * context.feePercent)
|
const fee = Math.floor(grossSats * context.feePercent)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue