feat(machine): NFC Bolt Card reader driver + IPC (main process)
Main-process driver over nfc-pcsc (PC/SC). On tap it reads the NTAG424 Type-4 NDEF file via ISO7816 APDUs (select NDEF app D2760000850101 → select file → ReadBinary NLEN + message) and extracts the lnurlw voucher (fresh SUN p/c per tap), forwarding it to the renderer on `nfc:card-tapped` (+ `nfc:status`). Lazy, guarded import — a missing reader/pcscd just reports 'unavailable', never breaking the cash-out QR path. Preload removeAllListeners guards against a double payment-trigger on renderer reload. - electron/nfc-service.ts: startNfcReader() + readNdefLnurlw()/extractLnurlw(). - electron/nfc-service.test.ts: 7 tests (NDEF URI extraction, Type-4 read sequence incl. AID select, empty-file + select-fail handling). - main.ts start + IPC forward; preload + electron.d.ts listeners. - add nfc-pcsc dep (native @pokusew/pcsclite; nix build handling next). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
74c420fbd3
commit
84d746a0da
7 changed files with 281 additions and 1 deletions
|
|
@ -43,6 +43,7 @@ import {
|
|||
} from './state-store.js'
|
||||
import { initializeHal, type HalInstance } from './hal-service.js'
|
||||
import { executeLnurlWithdraw } from './lnurl-withdraw.js'
|
||||
import { startNfcReader, type NfcStatus } from './nfc-service.js'
|
||||
|
||||
// ESM equivalent of __dirname
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
|
|
@ -828,6 +829,14 @@ app.whenReady().then(() => {
|
|||
startWatchdog()
|
||||
startCommandPoller()
|
||||
|
||||
// Bolt Card reader — forwards taps (lnurlw) + status to the renderer. Fully
|
||||
// best-effort: if the reader/pcscd is absent it just reports 'unavailable'
|
||||
// and the cash-out QR path is unaffected.
|
||||
void startNfcReader(
|
||||
(lnurlw) => mainWindow?.webContents.send('nfc:card-tapped', lnurlw),
|
||||
(status) => mainWindow?.webContents.send('nfc:status', status)
|
||||
)
|
||||
|
||||
app.on('activate', () => {
|
||||
// macOS: re-create window when dock icon clicked
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue