padreug opened issue aiolabs/lightning-pub#11

padreug
2026-04-01T16:39:53Z

11#Extension: Satoshi Machine (DCA Distribution)#

Summary

Implement a Nostr-native DCA (Dollar Cost Averaging) distribution extension for Lightning.Pub, replacing the LNbits satmachineadmin + satmachineclient extensions with a single extension that uses Nostr events instead of SSH database polling.

Motivation

The current LNbits DCA system works by SSH-tunneling into a Lamassu ATM's PostgreSQL database to poll for cash-out transactions, then distributing BTC proportionally to registered clients. This is fragile (SSH tunnels, credential management, hourly polling) and fundamentally HTTP-dependent.

In the lamassu-next architecture, the ATM already communicates via Nostr (kind 30079 transaction records). A Lightning.Pub extension can subscribe to these events in real-time instead of polling a remote database.

Architecture Comparison

LNbits Approach | Lightning.Pub Approach
SSH tunnel to Lamassu PostgreSQL | Subscribe to Nostr kind 30079 transaction events
HTTP API with wallet keys | Nostr RPC methods
Separate admin + client extensions | Single extension, role by pubkey
Hourly polling task | Real-time Nostr event subscription via onNostrEvent()
LNbits internal payments | payInvoice() through ExtensionContext

Scope

RPC Methods:

satmachine.registerClient       satmachine.listClients
satmachine.createDeposit        satmachine.confirmDeposit
satmachine.getBalance           satmachine.getTransactions
satmachine.triggerDistribution  satmachine.getConfig
satmachine.updateConfig         satmachine.exportHistory

Core Logic (ports from LNbits):

Commission calculation engine: base_amount = total_amount / (1 + effective_commission)

Flow mode: proportional distribution based on client balance ratios

Fixed mode: daily limit-based allocation

Complete audit trail of all transactions and distributions

Data Model:

DcaClient — pubkey, identifier, mode (flow/fixed), daily_limit, status

DcaDeposit — client_id, fiat_amount, fiat_currency, status (pending/confirmed), confirmed_at

DcaPayment — client_id, amount_sats, payment_hash, triggered_by (transaction event ID)

DcaConfig — commission_percentage, discount, distribution_mode, source settings

ProcessedTransaction — nostr_event_id, crypto_atoms, fiat_amount, processed_at

ExtensionContext API usage:

onNostrEvent() to subscribe to ATM transaction events (kind 30079)

payInvoice() for distributing sats to clients

createInvoice() for deposit collection

onPaymentReceived() to confirm deposits

sendEncryptedDM() for notifying clients of distributions

registerMethod() for all operations

Complexity

MEDIUM — ~2000-3000 lines of TypeScript. 3-5 days estimated.

The commission math and distribution logic are non-trivial but well-defined. The biggest win is replacing SSH polling with Nostr event subscription.

Strategic Value

This closes the loop on the ATM ecosystem: lamassu-next ATM → Nostr → Lightning.Pub → DCA extension → client wallets. No LNbits, no SSH tunnels, no HTTP APIs in the critical path.

Reference

LNbits satmachineadmin: lnbits/extensions/satmachineadmin/

LNbits satmachineclient: lnbits/extensions/satmachineclient/

lamassu-next transaction records: kind 30079 events

Commission calculation: satmachineadmin/transaction_processor.py