From 10293d0ab523d9e54a566f56a47664cd3b075946 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sun, 22 Feb 2026 20:20:51 -0500 Subject: [PATCH] fix(machine): auto-init HAL in production, wire dispense completion, add GTQ - App.vue detects Electron and calls initializeForProduction() to start real hardware drivers instead of Lightning-only mode - Auto-send CASH_DISPENSED when HAL is active since dispenseCash already waits for bills to be removed before resolving - Add GTQ (Guatemalan Quetzal) bill lengths to F56 and Puloon dispensers Co-Authored-By: Claude Opus 4.6 --- apps/machine/src/App.vue | 10 ++++++++-- apps/machine/src/stores/atm.ts | 11 +++++++++++ packages/hal/src/dispensers/f56/bills.ts | 12 ++++++++++++ packages/hal/src/dispensers/puloon/bills.ts | 1 + 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apps/machine/src/App.vue b/apps/machine/src/App.vue index 90115e7..0a43177 100644 --- a/apps/machine/src/App.vue +++ b/apps/machine/src/App.vue @@ -9,14 +9,20 @@ const atmStore = useAtmStore() const { current: currentTheme, themes } = useTheme() const debugExpanded = ref(false) const network = import.meta.env.VITE_NETWORK || 'regtest' +const isElectron = typeof window !== 'undefined' && window.electronAPI !== undefined function formatSats(sats: number): string { return sats.toLocaleString() } onMounted(async () => { - // Initialize the ATM state machine with Lightning.Pub - await atmStore.initializeWithLightning() + if (isElectron) { + // Production: initialize with real hardware + Lightning + await atmStore.initializeForProduction() + } else { + // Browser dev mode: Lightning-only (no hardware) + await atmStore.initializeWithLightning() + } }) function toggleLiveServices() { diff --git a/apps/machine/src/stores/atm.ts b/apps/machine/src/stores/atm.ts index 96bc12b..058b932 100644 --- a/apps/machine/src/stores/atm.ts +++ b/apps/machine/src/stores/atm.ts @@ -209,6 +209,17 @@ export const useAtmStore = defineStore('atm', () => { if ('cashOut' in state) currentNested = state.cashOut as string } + // Auto-advance past waitingForCashTaken when HAL is connected, + // because HAL's dispenseCash already calls waitForBillsRemoved() + if ( + currentNested === 'waitingForCashTaken' && + prevNestedState !== 'waitingForCashTaken' && + halServices.value + ) { + console.log('[ATM] HAL active — bills already removed, auto-advancing') + send({ type: 'CASH_DISPENSED' }) + } + if (currentNested === 'complete' && prevNestedState !== 'complete' && prevSnapshot) { const ctx = newSnapshot.context if (ctx.txid) { diff --git a/packages/hal/src/dispensers/f56/bills.ts b/packages/hal/src/dispensers/f56/bills.ts index 7ed313a..dad459c 100644 --- a/packages/hal/src/dispensers/f56/bills.ts +++ b/packages/hal/src/dispensers/f56/bills.ts @@ -75,6 +75,18 @@ export const bills: Record = { }, polymer: false, }, + GTQ: { + thickness: 0x0c, + lengths: { + 5: [0xa3, 0x99], + 10: [0xa1, 0x97], + 20: [0xa3, 0x99], + 50: [0xa1, 0x97], + 100: [0xa1, 0x97], + 200: [0xa1, 0x97], + }, + polymer: false, + }, GBP: { thickness: 0x0d, lengths: { diff --git a/packages/hal/src/dispensers/puloon/bills.ts b/packages/hal/src/dispensers/puloon/bills.ts index c20546e..219c020 100644 --- a/packages/hal/src/dispensers/puloon/bills.ts +++ b/packages/hal/src/dispensers/puloon/bills.ts @@ -14,6 +14,7 @@ export const billLengths: Record> = { DKK: { 50: 125, 100: 135, 200: 145, 500: 155, 1000: 165 }, EUR: { 5: 120, 10: 127, 20: 133, 50: 140, 100: 147, 200: 153, 500: 160 }, GBP: { 5: 135, 10: 142, 20: 149, 50: 156 }, + GTQ: { 5: 156, 10: 156, 20: 156, 50: 156, 100: 156, 200: 156 }, HKD: { 10: 134, 20: 143, 50: 148, 100: 153, 500: 158, 1000: 163 }, HUF: { 200: 154, 500: 154, 1000: 154, 2000: 154, 5000: 154, 10000: 154, 20000: 154 }, ILS: { 20: 129, 50: 136, 100: 143, 200: 150 },