From 5fa2dcb992521073bf9a6ee8be7378e9f45941a9 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Tue, 31 Mar 2026 11:11:53 -0400 Subject: [PATCH] feat(state-machine): add inactivity timeouts to prevent stuck screens insertingBills and selectingAmount now auto-idle after 3 minutes of inactivity. displayingInvoice returns to amount selection after 5 minutes if the customer never pays. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/state-machine/src/machine.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/state-machine/src/machine.ts b/packages/state-machine/src/machine.ts index 377f58b..4d448b2 100644 --- a/packages/state-machine/src/machine.ts +++ b/packages/state-machine/src/machine.ts @@ -390,6 +390,8 @@ export function createATMMachine( }, delays: { TIMEOUT_MS: 300000, // 5 minutes + INACTIVITY_TIMEOUT: 180000, // 3 minutes — no-interaction screens + INVOICE_TIMEOUT: 300000, // 5 minutes — waiting for payment COMPLETE_DELAY: 60000, DISPENSE_TIMEOUT: 120000, // 2 min max for hardware to respond DISPENSE_ERROR_TIMEOUT: 30000, // 30s like brain.js _timedState @@ -435,6 +437,17 @@ export function createATMMachine( }, }, insertingBills: { + after: { + INACTIVITY_TIMEOUT: [ + { + guard: ({ context }) => context.billsInserted.length === 0, + target: '#atm.idle', + }, + { + target: 'confirmAbandon', + }, + ], + }, on: { BILL_INSERTED: { guard: 'billWithinBalance', @@ -612,6 +625,9 @@ export function createATMMachine( selectingAmount: { // User selects denomination buttons to build up the cash amount // UI shows: available denominations, running total, sats equivalent + after: { + INACTIVITY_TIMEOUT: '#atm.idle', + }, entry: 'clearCashOutSelection', on: { ADD_DENOMINATION: { @@ -653,6 +669,11 @@ export function createATMMachine( }, displayingInvoice: { // Show QR code with BOLT11 invoice, watch for payment + after: { + INVOICE_TIMEOUT: { + target: 'selectingAmount', + }, + }, invoke: { src: 'watchInvoicePayment', input: ({ context }) => ({ invoice: context.invoice! }),