feat(docker): add dev.sh with auto-funding and ATM app setup

- Add dev.sh script for managing regtest development environment
- Implement cmd_fund to fund ATM app owner via Lightning.Pub API
- Add --fund flag to cmd_up for automatic funding on startup
- Update setup_atm_app to write VITE_APP_ID to machine .env
- Fix Electron IPC to pass appId and extensionApiUrl to renderer
- Restructure repo from nested lamassu-next/ to root

The dev.sh script now supports:
- ./dev.sh up --fund  # Start regtest and auto-fund ATM
- ./dev.sh fund       # Fund existing ATM app
- ./dev.sh status     # Show environment status
- ./dev.sh reset      # Clean restart

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Patrick Mulligan 2026-02-15 14:19:16 -05:00
commit c98f126ba7
180 changed files with 2695 additions and 9587 deletions

404
CLAUDE.md
View file

@ -1,121 +1,339 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This file provides guidance to Claude Code when working with the Lamassu Next codebase.
## Repository Overview
## Project Overview
This is the Lamassu Bitcoin ATM system, consisting of three components:
**Lamassu Next** is a Nostr-native Lightning ATM system. Key principles:
- **lamassu-server/** - Backend services and admin dashboard (pnpm monorepo with Turbo)
- **lamassu-machine/** - ATM kiosk software that runs on the physical machines
- **lamassu-install/** - Production installation and upgrade scripts
## Commands
### lamassu-server (monorepo)
```bash
cd lamassu-server
# Install dependencies
pnpm install
# Run all packages in development mode (server + admin-ui)
pnpm run dev
# Build all packages
pnpm run build
# Run tests across all packages
pnpm run test
# Run a single test file
cd packages/admin-ui && pnpm vitest run path/to/file.test.js
# Database migrations
node packages/server/bin/lamassu-migrate
# Generate SSL certificates (first-time setup)
bash packages/server/tools/cert-gen.sh
# Create admin user
node packages/server/bin/lamassu-register admin@example.com superuser
# Regenerate database types (requires running postgres)
cd packages/typesafe-db && pnpm run generate-types
```
### lamassu-machine
```bash
cd lamassu-machine
# Install and build
npm install
bash ./setup.sh
npm run build
# Run tests
npm test
# Development with mock hardware
node bin/fake-bills.js # In one terminal
node bin/lamassu-machine --mockBillValidator --mockBillDispenser --mockCam --mockPair '<totem>'
```
- **KYC-Free**: No identity collection, no compliance theater
- **Lightning-Native**: Security encapsulated in Lightning protocol
- **Nostr as Infrastructure**: Relay for communication, keypairs for identity
- **Open Source First**: Every component auditable and forkable
## Architecture
### lamassu-server Monorepo Structure
```
packages/
├── server/ # Express + Apollo GraphQL backend (CommonJS)
├── admin-ui/ # React 18 + Vite + MUI admin dashboard (ESM)
├── coins/ # @lamassu/coins - cryptocurrency constants (TypeScript)
└── typesafe-db/ # @lamassu/typesafe-db - Kysely database layer (TypeScript)
lamassu-next/
├── apps/
│ ├── machine/ # Electron + Vue 3 ATM kiosk application ✅
│ ├── dashboard/ # Vue 3 operator dashboard (planned)
│ └── relay/ # strfry relay configuration (planned)
├── packages/
│ ├── hal/ # TypeScript Hardware Abstraction Layer ✅
│ ├── nostr-client/ # Nostr client library ✅
│ ├── clink/ # CLINK protocol implementation ✅
│ ├── state-machine/ # XState v5 ATM state machine ✅
│ ├── lightning/ # Lightning.Pub RPC client ✅
│ ├── cashu/ # Cashu ecash (placeholder)
│ └── ui-shared/ # Shared Vue components (placeholder)
└── docker/ # Development infrastructure ✅
```
**Dependency flow**: `server` and `admin-ui` depend on `coins` and `typesafe-db`
## Implementation Status
**Key server entry points**:
- `bin/lamassu-server` - Main HTTPS server (port 3000, client cert auth)
- `bin/lamassu-admin-server` - Admin API server
- 20+ CLI utilities in `bin/` for operations tasks
### Completed Packages
**GraphQL**: Two implementations exist:
- `lib/graphql/` - Machine-facing API
- `lib/new-admin/graphql/` - Admin dashboard API
| Package | Description | Tests |
| ------------------------ | ------------------------------------------------------ | ----- |
| `@lamassu/nostr-client` | Nostr relay client with NIP-42 auth, NIP-44 encryption | 13 |
| `@lamassu/clink` | CLINK protocol (kinds 21001-21003), noffer encoding | 7 |
| `@lamassu/lightning` | Lightning.Pub RPC client (kind 21000) | 10 |
| `@lamassu/state-machine` | XState v5 ATM state machine (idle, cashIn, cashOut) | 14 |
| `@lamassu/hal` | Hardware drivers (ID003 validator, F56 dispenser) | - |
### lamassu-machine
### Placeholder Packages
The ATM kiosk uses a state machine architecture (`machina.js`) in `lib/brain.js` (134KB). The UI is vanilla JavaScript with Babel transpilation.
| Package | Description |
| -------------------- | --------------------------------- |
| `@lamassu/cashu` | Cashu ecash for offline operation |
| `@lamassu/ui-shared` | Shared Vue 3 components |
**Hardware drivers** in `lib/`: id003, mei, puloon, ccnet (bill validators), printer, leds, camera
### Completed Applications
- **apps/machine** - Electron ATM kiosk with Vue 3 UI (HAL integrated, ready for hardware testing)
### Planned Components
- **apps/dashboard** - Operator dashboard for fleet management
### Critical Documentation
- **`packages/lightning/TROUBLESHOOTING.md`** - Lightning.Pub integration gotchas. Read this BEFORE debugging payment issues. Contains solutions to 9 non-obvious issues that took 5+ hours to diagnose.
## Commands
```bash
# Enter development environment
devenv shell
# Start development
pnpm dev
# Build all packages
pnpm build
# Run tests
pnpm test
# Infrastructure management
infra-up # Start all Docker services
infra-down # Stop all Docker services
infra-status # Show service status
infra-logs # Follow service logs
# Bitcoin/Lightning (regtest)
btccli # Bitcoin CLI
lncli # LND CLI (Lightning.Pub's node)
lncli-alice # LND CLI (Alice's node for testing payments)
mine-blocks # Mine regtest blocks (default: 1)
setup-channel # Setup channel between Alice and LND
alice-pay # Pay invoice from Alice's node
relay-test # Test Nostr relay connection
# Testing (E2E)
test-setup # Validate test environment (services, channels, payments)
test-payment # Quick e2e payment test (ATM → customer)
fund-atm # Fund ATM account (default: 100k sats)
alice-invoice # Create invoice on Alice's node
node-info # Show node pubkeys and channel info
```
## Development Infrastructure
The `docker/` directory contains a complete development environment:
| Service | Container | Port(s) | Description |
| ------------- | --------------------- | ----------- | ------------------------------------- |
| strfry | lamassu-relay | 7777 | Private Nostr relay |
| bitcoind | lamassu-bitcoind | 18443 | Bitcoin Core (regtest) |
| LND | lamassu-lnd | 10009, 8080 | Lightning node (Lightning.Pub's node) |
| LND Alice | lamassu-lnd-alice | 10010, 8081 | Second LND for payment testing |
| Lightning.Pub | lamassu-lightning-pub | 1776 | Nostr-native account system |
| PostgreSQL | lamassu-postgres | 5432 | Database for server-side state |
### Quick Start
```bash
devenv shell # Enter dev environment
infra-up # Start all services (30-60s first run)
mine-blocks 101 # Fund the regtest wallet
setup-channel # Open channel between Alice and LND
```
### Testing Payments
The development setup includes two LND nodes to enable proper payment testing:
1. **LND** (`lamassu-lnd`) - Used by Lightning.Pub to create invoices
2. **Alice** (`lamassu-lnd-alice`) - Used to pay invoices (simulates external payers)
```bash
# Get Lightning.Pub admin token
curl -X POST "http://localhost:1776/api/admin/app/auth" \
-H "Authorization: Bearer lamassu-dev-admin-token" \
-d '{"name": "wallet"}'
# Create user and invoice
curl -X POST "http://localhost:1776/api/app/user/add" -H "Authorization: Bearer $APP_TOKEN" \
-d '{"identifier": "test-user", "balance": 0}'
curl -X POST "http://localhost:1776/api/app/user/add/invoice" -H "Authorization: Bearer $APP_TOKEN" \
-d '{"receiver_identifier": "test-user", "payer_identifier": "external", "http_callback_url": "", "invoice_req": {"amountSats": 1000, "memo": "Test"}}'
# Pay from Alice
alice-pay <invoice>
```
### Comprehensive Regtest Integration
For advanced testing with multiple Lightning implementations, use the regtest environment at `~/dev/local/docker/regtest`. This provides:
| Service | Description |
| ----------------- | ------------------------------------- |
| 4 LND nodes | lnd-1 (hub), lnd-2 (Boltz), lnd-3 (LNbits), lnd-4 (standalone) |
| 3 CLN nodes | Core Lightning with REST/gRPC |
| 1 Eclair node | ACINQ Eclair implementation |
| LNbits | Lightning wallet platform (port 5001) |
| Boltz | Submarine swaps (port 9001) |
| Electrs | Electrum server (port 3002) |
| Lightning Terminal| Web UI for lnd-1 (port 8443) |
| Elements/Liquid | Sidechain (port 18884) |
```bash
# Start regtest environment
cd ~/dev/local/docker/regtest && ./start-regtest
source docker-scripts.sh
# Start lamassu services connected to regtest
cd lamassu-next/docker && ./start-with-regtest.sh
# CLI helpers
bitcoin-cli-sim -generate 1 # Mine blocks
lncli-sim 4 getinfo # lnd-4 (Lightning.Pub's node)
lightning-cli-sim 1 getinfo # CLN node 1
```
The integration uses `lnd-4` as Lightning.Pub's backend, giving you access to test payments from multiple node types (LND, CLN, Eclair) and services (LNbits, Boltz).
### MCP Tools Available
Claude has access to these MCP servers for development:
| MCP Server | Purpose |
| ------------ | ----------------------------------------- |
| docker-mcp | Container management (logs, status, etc.) |
| nostr-mcp | Nostr operations (post notes, profiles) |
| postgres-mcp | Database queries and schema inspection |
| mcp-nixos | NixOS/Nix package queries |
| forgejo-mcp | Git operations on Forgejo |
Use these to interact with infrastructure directly during development.
## Key Technologies
| Component | Technology | Notes |
| ------------- | -------------- | --------------------------------------- |
| Runtime | Node.js 22 LTS | Strict TypeScript, ESM |
| ATM Shell | Electron | Node.js main process, Vue 3 renderer |
| State Machine | XState v5 | Actor model, service injection |
| Hardware | TypeScript | ID003, F56 drivers from lamassu-machine |
| Messaging | Nostr | NIP-01, NIP-42, NIP-44 |
| Payments | CLINK + RPC | Kind 21000 (RPC), 21001-21003 (CLINK) |
| Backend | Lightning.Pub | Nostr-native account system |
## Custom Skills
The following skills are available for development assistance:
### `/security` - Security Review
Audit code for Bitcoin/Lightning/ATM-specific vulnerabilities.
```
/security packages/lightning/src/
/security --staged
```
### `/nostr-check` - Nostr Conformity
Validate NIP compliance and Nostr protocol implementation.
```
/nostr-check packages/nostr-client/src/events.ts --nips NIP-01,NIP-44
```
### `/lightning-check` - Lightning.Pub Conformity
Validate CLINK protocol and Lightning.Pub integration.
```
/lightning-check packages/clink/src/ --clink
```
### `/test` - Testing Agent
Run tests, generate test cases, validate transaction flows.
```
/test coverage packages/state-machine/
/test flow cash-out
/test generate packages/lightning/src/client.ts
```
### `/docs` - Documentation Agent
Keep documentation synchronized with code.
```
/docs sync packages/clink/
/docs api packages/nostr-client/src/
```
### `/hal-check` - HAL Validation
Validate Rust HAL drivers against lamassu-machine implementations.
```
/hal-check port id003
/hal-check safety packages/hal/src/dispensers/
```
## Code Style
**Formatting** (enforced by husky pre-commit):
- 2-space indent, no semicolons, single quotes, trailing commas
- Prettier + ESLint with auto-fix on commit
### TypeScript
**TypeScript**: Only in `packages/coins/` and `packages/typesafe-db/`. Use `@typescript-eslint/consistent-type-imports` for imports.
- ESM only (`import`/`export`)
- Strict mode with `strictNullChecks` and `noUncheckedIndexedAccess`
- Zod for runtime validation
- No `any` types
**Server code**: CommonJS (`require`/`module.exports`)
**Admin UI**: ESM (`import`/`export`)
### Rust (HAL)
## Database
- Stable toolchain
- `#![deny(unsafe_code)]` unless justified
- Error handling with `thiserror`
- Async with `tokio`
PostgreSQL with Kysely ORM. Types are auto-generated from the schema.
### Formatting
**Environment**: Configure postgres connection in `packages/server/.env`
- Prettier for TypeScript (2 spaces, no semicolons, single quotes)
- rustfmt for Rust
- Pre-commit hooks enforce formatting
## Requirements
## Hardware Drivers
- Node.js 22+
- pnpm 10+
- PostgreSQL
- Python 3 (for native dependency builds)
Drivers are ported from `lamassu-machine/lib/`:
## Documentation
| Category | Drivers |
| ---------- | ------------------------------------------------------------ |
| Validators | id003, ccnet, cashflow_sc, bnr_advance, genmega, hcm2, gsr50 |
| Dispensers | puloon, f56, genmega, hcm2, gsr50 |
| Printers | nippon, zebra, genmega |
- `docs/modernization-plan.md` - 2026 modernization roadmap (Obsidian-compatible)
When porting:
1. Read JS driver thoroughly
2. Document protocol from JS code
3. Implement Rust version
4. Test against same hardware
5. Use `/hal-check port <driver>` to validate
## Nostr Event Kinds
| Kind | Description |
| ----- | ----------------------------------------------- |
| 21000 | Lightning.Pub RPC (generic request/response) |
| 21001 | CLINK Offer (invoice request/response) |
| 21002 | CLINK Debit (payment authorization) |
| 21003 | CLINK Manage (offer management) |
| 30078 | Service Beacon (replaceable, service discovery) |
| 30079 | Transaction Record (replaceable) |
## Security Priorities
1. **Private keys** - Never log nsec, protect with 0600 permissions
2. **Payments** - Validate invoices, verify preimages, prevent double-pay
3. **Hardware** - Validate dispense amounts, handle errors gracefully
4. **Encryption** - Use NIP-44 for all sensitive data
## Testing Requirements
- Unit tests for all packages
- Integration tests for cross-package interactions
- E2E tests for full transaction flows
- **Cash-out flow is critical path** (95%+ of activity)
## Related Documentation
- `docs/architecture-comparison.md` - Nostr-native vs traditional lamassu-server comparison
- `docs/ndebit-cash-in-flow.md` - Technical walkthrough of cash-in implementation
- `packages/lightning/TROUBLESHOOTING.md` - Lightning.Pub integration gotchas (must read!)
- `.claude/skills/*.md` - Custom skill documentation
## External Resources
- [CLINK Protocol Spec](https://github.com/shocknet/clink)
- [Lightning.Pub](https://github.com/shocknet/Lightning.Pub)
- [NIP-44 Encryption](https://github.com/nostr-protocol/nips/blob/master/44.md)
- [LND Hold Invoices](https://docs.lightning.engineering/lightning-network-tools/lnd/hold-invoices)