Commit graph

422 commits

Author SHA1 Message Date
Patrick Mulligan
94a9f03e2e fix(hal): simplify Puloon error handling to match lamassu-machine
Align dispenser error handling with lamassu-machine's proven approach:
close port on error, set error name, let caller decide when to re-init.
Also configure live ISO for Douro/GTQ with serialport native modules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:22:34 -05:00
Patrick Mulligan
10293d0ab5 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 <noreply@anthropic.com>
2026-02-22 20:20:51 -05:00
Patrick Mulligan
ba42820c71 feat(machine): add Tejo machine preset with 4-cassette F56 dispenser
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:04:29 -05:00
Patrick Mulligan
350e7a8974 feat(hal): add Puloon bill dispenser driver for Douro ATM
Port the Puloon RS232 dispenser protocol from lamassu-machine to
the lamassu-next HAL package. Adds Douro machine preset with Puloon
dispenser on /dev/ttyS1 and ID003 validator on /dev/ttyS0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 20:01:26 -05:00
Patrick Mulligan
658c3c2b4d fix(machine): live USB ISO with native modules and debug mode
Enable debugMode by default (simulated bill buttons) until real
hardware validator is connected. Fix live.nix to include native
node_modules (better-sqlite3, bindings) from pnpm virtual store,
add LD_LIBRARY_PATH for NixOS, bake aiolabs.dev endpoints into
env template, and enable Electron renderer logging in journalctl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:14:35 -05:00
Patrick Mulligan
3634509ed4 fix(machine): mobile UI polish and shadcn-vue ScrollArea
- Use h-dvh instead of h-screen for mobile browser viewport
- Add ScrollArea component (shadcn-vue) to replace native scrollbars
- Move Hide Debug into debug bar row, show Show Debug only when off
- Responsive cash-out denomination grid (single col on mobile)
- Add safe-area padding for mobile gesture bar
- Add business model documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:44:39 -05:00
Patrick Mulligan
98e373c5ce fix(machine): make debug bar in-flow and slim down bill acceptor
- Debug bar is now a normal flex child (shrink-0) instead of fixed
  overlay, so content naturally fits above it without padding hacks
- Replace bulky dashed bill acceptor box with a single text line

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:45:24 -05:00
Patrick Mulligan
56e7aa5f24 fix(machine): add min-h-0 to view roots so content scrolls above debug bar
Without min-h-0, flex children won't shrink below their content size,
so the parent's pb-28 padding is ignored and the debug bar overlaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:36:22 -05:00
Patrick Mulligan
b6b544d45a fix(machine): responsive mobile layout for cash-in/cash-out views
- Push header below fixed status badges on mobile (pt-12)
- Use w-full max-w-* instead of fixed widths so cards fit mobile screens
- Make main content scrollable with overflow-auto
- Reduce padding on mobile (p-4 vs p-8)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:31:22 -05:00
Patrick Mulligan
1f312abcaf fix(machine): increase bottom padding for debug bar on mobile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:55:58 -05:00
Patrick Mulligan
b3b156c3ed fix(machine): add bottom padding when debug bar is active
Prevents the fixed debug overlay from covering content (QR links)
on mobile by reserving space at the bottom of the main container.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:52:26 -05:00
Patrick Mulligan
a0e0c98573 fix(machine): wrap debug footer so theme buttons don't get cut off
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:50:10 -05:00
Patrick Mulligan
a9da1067b3 feat(machine): responsive mobile-friendly layout with Tailwind v4
- IdleView: stack cards vertically on mobile, side-by-side on sm+
- Scale logo, cards, text, and badges down for small screens
- QR overlays use smaller codes on mobile (280px vs 400px)
- Status badges wrap and use smaller text on mobile
- Hide subtitle text on mobile cards to save space

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:47:26 -05:00
Patrick Mulligan
e40545671e fix(machine): stack idle view sections vertically instead of inline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:44:32 -05:00
Patrick Mulligan
1023e459aa fix(machine): prefix balance badge with "bal:" for clarity
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:42:33 -05:00
Patrick Mulligan
45975bccd4 feat(machine): add regtest network badge and rename Zeus lnd-3 to lnd-alice
Shows a warning-colored badge with the network name (regtest/testnet) when
not on mainnet. Also renames Zeus QR references from lnd-3 to lnd-alice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:33:11 -05:00
Patrick Mulligan
f37555565e feat(machine): add SQLite persistence and remove npub linking
Add crash-safe persistence for cassette inventory, cashbox state, and
transaction history using better-sqlite3 in the Electron main process.
The state machine now loads inventory from the database at runtime
instead of using hardcoded values, and transactions are automatically
persisted on completion.

Remove the unnecessary npub linking code — Lightning.Pub auto-creates
and associates Nostr users when appId is included in RPC requests,
making the HTTP-based user creation and token linking redundant.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:45:09 -05:00
Patrick Mulligan
722635a5a6 feat(machine): landscape layout and fullscreen mode
- Switch Electron window to landscape (1920x1080) with fullscreen fallback
- Rearrange IdleView for horizontal layout (logo+badges left, action cards right)
- Fix hostname command in provision/build scripts (use ip route instead of hostname -I)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 20:43:49 -05:00
Patrick Mulligan
19d43c2939 feat(deploy): add NixOS live USB ISO for ATM hardware testing
Add NixOS configuration to build a bootable live USB ISO that runs the
ATM Electron app in kiosk mode on physical hardware (UpBoard). The ISO
boots from squashfs, auto-starts X11/openbox, and launches Electron in
production mode.

Key changes:
- deploy/nixos/live.nix: Live USB module (squashfs+tmpfs, no disk install)
- deploy/nixos/flake.nix: Nix flake with ISO build output
- deploy/nixos/provision-atm.sh: Auto-provision LP credentials via API
- deploy/nixos/build-iso.sh: End-to-end build workflow script
- apps/machine: Fix Electron production mode (ELECTRON_FORCE_PROD),
  Vue Router hash mode for file:// protocol, relative asset paths

Build: cd deploy/nixos && bash build-iso.sh
Test:  qemu-system-x86_64 -enable-kvm -m 2G -cdrom result/iso/*.iso

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 20:11:23 -05:00
Patrick Mulligan
c8e5bf9ee1 fix(docker): ensure wallet loaded before mining in regtest
bitcoin-cli -generate requires a loaded wallet, but Bitcoin Core 25+
no longer auto-creates one. After bitcoind restarts the miner loop
silently failed, causing the chain to go stale and LND to report
synced_to_chain: false.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 14:39:26 -05:00
Patrick Mulligan
60f4eb6639 feat(machine): add Zeus and Lightning.Pub QR codes to mock UI
dev.sh atm auto-injects VITE_LNDCONNECT_URL from lnd-3 credentials.
Idle screen shows "Zeus QR" and "Lightning.Pub nprofile" buttons (debug
mode) that open fullscreen overlays with scannable 400px QR codes and
copy-to-clipboard support. Also makes the debug overlay collapsible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 13:38:32 -05:00
Patrick Mulligan
333b8b9357 feat(machine): add logo with float animation to idle screen
Integrate pyramid logo into idle view with a gentle floating animation
and theme-aware glow. Rename title to Bitcoinmat, enlarge action cards,
and use BitcoinIcon for Buy Bitcoin / cash emoji for Sell Bitcoin.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 21:18:02 -05:00
Patrick Mulligan
b0fc5cf585 feat(machine): add 6 switchable color themes
Add theme system with Gruvbox (default), Catppuccin, Dracula, Nord,
Tokyo Night, and Cyberpunk palettes — each with light/dark variants.
Theme picker on idle screen and debug overlay, persisted to localStorage.

Also fixes @custom-variant dark to use :where() per Tailwind v4 best
practice, and replaces Buy Bitcoin emoji with BitcoinIcon component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 21:03:20 -05:00
Patrick Mulligan
55ea9f8175 fix(docker): reduce miner interval to 30s to keep LND synced
2-minute interval caused chain staleness between blocks, making LND
report synced_to_chain: false. Zeus rejects payments when the node
is not synced. 30s keeps all nodes in sync reliably.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 20:13:01 -05:00
Patrick Mulligan
5448a620a9 chore(nostr-client): move dev scripts to dev/ folder
Move 9 development/testing .mjs scripts out of the package root into
dev/ to keep the published package clean. Update relative imports
and dev.sh reference.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:48:49 -05:00
Patrick Mulligan
01bac04cdf chore(machine): remove unused express dependency
express is only used in Lightning.Pub's withdraw extension for LNURL
HTTP endpoints, not in the ATM Electron/Vue app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:44:27 -05:00
Patrick Mulligan
3f0247313d feat(machine): add optimized BitcoinIcon component
SVGO-optimized bitcoin.svg (62% smaller) as a reusable Vue component
with configurable size prop. Used in CashInView balance limit message
instead of dollar-sign emoji.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:33:33 -05:00
Patrick Mulligan
16159334a4 feat(machine): limit bill insertion to available balance
Add billWithinBalance guard to state machine that rejects bills
exceeding the ATM's available sats. UI disables denomination buttons
and shows informational message when limit is reached.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:21:45 -05:00
Patrick Mulligan
9569f849e7 fix(machine): track relay connection state for live status badge
Listen for nostrClient disconnect/connect events to update the
connection status badge. Previously it was set once on init and
never reflected WebSocket disconnections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:05:14 -05:00
Patrick Mulligan
e6e77f808e feat(docker): add fund command and Nostr RPC funding script
- Add './dev.sh fund [amount]' for funding ATM via Nostr RPC
- Create invoices via NIP-44 encrypted RPC instead of HTTP API
- Support existing users without fail_if_exists errors
- Add --fund flag to './dev.sh up' for one-command setup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:58:32 -05:00
Patrick Mulligan
c4fadd7438 feat(machine): add Electron serial port IPC for hardware access
Expose serialport APIs through Electron preload for bill validator
and dispenser communication. Update HAL service with device path
configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:58:19 -05:00
Patrick Mulligan
b410917e52 feat(machine): LNURL-withdraw support and real-time balance display
- Add LNURL-withdraw as payment option in cash-in flow
- Generate withdraw links via Nostr RPC (NIP-44 encrypted)
- Poll withdraw link status to detect wallet claims
- Add npub linking during Lightning.Pub initialization
- Display live balance badge in ATM UI header
- Subscribe to balance updates via LiveUserOperation events

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:58:05 -05:00
Patrick Mulligan
c199431b8e feat(state-machine): fetch balance with exchange rate on cash-in
Add getRateAndBalance actor that fetches exchange rate and available
balance in parallel during cash-in flow. Add generateLnurlWithdraw
service type for LNURL-withdraw support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:57:30 -05:00
Patrick Mulligan
1e891765de feat(lightning): add withdraw links, balance watching, and npub linking
- Add createWithdrawLink/getWithdrawLink methods using Nostr RPC
- Add watchBalance with Nostr subscription + polling fallback
- Add linkNpub method for connecting Nostr identity to app user
- Fix getBalance to use GetUserInfo RPC instead of GetBalance
- Include appId in RPC requests for correct user resolution
- Add CreateWithdrawLinkParams, CreateWithdrawLinkResponse,
  GetWithdrawLinkResponse types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:57:21 -05:00
Patrick Mulligan
5e94cdc11b fix(docker): add extra delay after graph sync for reliable payments
Add 10-second delay after route verification succeeds to ensure
the graph is fully propagated before attempting funding payments.
Also increase max route check attempts from 12 to 15.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 18:43:50 -05:00
Patrick Mulligan
f6c3d62488 fix(docker): improve channel setup timing for clean slate
- Add is_lnd1_wallet_ready() to verify wallet is ready before operations
- Mine initial blocks if blockchain has < 101 blocks (fresh regtest)
- Wait for lnd-1 to sync to chain before opening channels
- Create bitcoind wallet if needed (clean slate)
- Increase channel activation wait from 40s to 60s
- Add explicit graph propagation check via queryroutes
- Wait up to 60s for lnd-3 to find route to lnd-4 before funding

This ensures the environment works from a completely clean Docker
slate without relying on the scheduled miner.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 18:25:32 -05:00
Patrick Mulligan
0b02fb9204 docs: document automatic channel setup in unified regtest mode
Add explanation of how dev.sh automatically sets up Lightning channels:
- lnd-1 as hub funds lnd-3 and lnd-4 via channels
- lnd-4 receives payments (Lightning.Pub backend)
- lnd-3 sends payments (ATM funding source)
- Mining ensures channel confirmation and graph propagation

This clarifies that the environment works from a clean Docker slate.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 17:55:54 -05:00
Patrick Mulligan
90eceeafd9 feat(docker): auto-setup Lightning channels for unified regtest mode
Add automatic channel setup to dev.sh for seamless ATM development:

- Add ensure_lnd4_channel() to open channels from lnd-1 hub to lnd-3 and lnd-4
- lnd-4 receives channel for Lightning.Pub invoice creation
- lnd-3 receives channel for paying invoices (ATM funding)
- Auto-fund lnd-1 via mining if balance is low
- Include retry logic for channel opening (5 attempts)
- Mine extra blocks and wait for graph propagation to avoid NO_ROUTE errors
- Show channel balance in status output

This makes the unified mode fully functional from a clean slate:
  ./docker/dev.sh up --fund    # Sets up regtest, channels, and funds ATM
  ./docker/dev.sh atm          # Launch ATM application

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 17:54:40 -05:00
Patrick Mulligan
c3564beccf feat(docker): add standalone mode and external orchestration support
- Add --standalone flag to use self-contained bitcoind/lnd
- Default to unified mode using shared regtest
- Track compose mode in state file for down/logs/reset
- Add _setup_after_start internal command for external orchestration
- Update help text with new options

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 16:03:13 -05:00
Patrick Mulligan
7c3ce0de5d docs: note regtest dependency in prerequisites
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 15:05:53 -05:00
Patrick Mulligan
0dafb7d8a8 docs: add new dev.sh commands to README
- Add atm, zeus, mine commands to table
- Add --machine flag documentation
- Ignore docker/.state/ directory (generated files)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 15:02:11 -05:00
Patrick Mulligan
e9ed63770a fix(docker): correct lnd-3 REST port to 8081
Was incorrectly set to 8082, causing Zeus connection to fail.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:54:31 -05:00
Patrick Mulligan
b46b415b4e fix(docker): generate PNG QR code for Zeus scanning
Terminal QR codes can be hard to scan. Generate a PNG file instead
and open it with the default image viewer.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:50:55 -05:00
Patrick Mulligan
8a3b38f352 feat(docker): add zeus command for QR code display
- Show truncated lndconnect in status instead of large QR
- Add ./dev.sh zeus command to display QR on demand

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:48:28 -05:00
Patrick Mulligan
ba3a54265f fix(docker): reduce QR code margin, add scan hint
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:41:00 -05:00
Patrick Mulligan
786b118d54 feat(docker): display Zeus lndconnect as QR code
- Add qrencode to devenv.nix packages
- Display QR code in terminal for easy Zeus wallet scanning
- Falls back to text if qrencode not available

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:38:40 -05:00
Patrick Mulligan
c8006638b2 refactor(docker): simplify lndconnect to use docker exec only
Remove filesystem fallback with sudo - just read certs from container.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:35:57 -05:00
Patrick Mulligan
f70c2b8878 fix(docker): run ATM in background, fix Zeus lndconnect
- Launch ATM with --background flag when using --machine
- ATM logs written to .state/atm.log instead of terminal
- Fix lndconnect generation to read certs via docker exec
- Status output remains visible after ATM starts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:34:09 -05:00
Patrick Mulligan
9a4dc759f8 feat(docker): add --machine flag to launch ATM with dev.sh up
Usage: ./dev.sh up --fund --machine

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:30:13 -05:00
Patrick Mulligan
bf8f9c3a22 docs: update README for dev.sh workflow and LNURL-withdraw
- Replace old devenv commands with dev.sh usage
- Document LNURL-withdraw as alternative cash-in method
- Update architecture to reflect Electron + Vue (not Tauri)
- Add HAL package to architecture overview
- Update infrastructure services table with regtest nodes
- Add troubleshooting for common dev.sh issues

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-15 14:23:39 -05:00