Extension: Satoshi Machine (DCA Distribution) #11
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implement a Nostr-native DCA (Dollar Cost Averaging) distribution extension for Lightning.Pub, replacing the LNbits
satmachineadmin+satmachineclientextensions 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
onNostrEvent()payInvoice()through ExtensionContextScope
RPC Methods:
Core Logic (ports from LNbits):
base_amount = total_amount / (1 + effective_commission)Data Model:
DcaClient— pubkey, identifier, mode (flow/fixed), daily_limit, statusDcaDeposit— client_id, fiat_amount, fiat_currency, status (pending/confirmed), confirmed_atDcaPayment— client_id, amount_sats, payment_hash, triggered_by (transaction event ID)DcaConfig— commission_percentage, discount, distribution_mode, source settingsProcessedTransaction— nostr_event_id, crypto_atoms, fiat_amount, processed_atExtensionContext API usage:
onNostrEvent()to subscribe to ATM transaction events (kind 30079)payInvoice()for distributing sats to clientscreateInvoice()for deposit collectiononPaymentReceived()to confirm depositssendEncryptedDM()for notifying clients of distributionsregisterMethod()for all operationsComplexity
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/extensions/satmachineadmin/lnbits/extensions/satmachineclient/satmachineadmin/transaction_processor.pyNIP Review: Applicable Standards for Satoshi Machine Extension
Core NIPs to Implement
NIP-47: Nostr Wallet Connect (NWC) — PAYMENT ENGINE
Kinds: 13194 (info), 23194 (request), 23195 (response), 23197 (notification)
The backbone for DCA distribution payments. Relevant methods:
pay_invoicemake_invoiceget_balancelist_transactionspay_keysendpay_keysendis particularly interesting — DCA distributions to registered clients (known pubkeys) could bypass invoice generation entirely.The
metadatafield (up to 4KB) stores distribution context: client ID, deposit reference, commission breakdown, batch ID.Key insight: NWC provides the authorization layer. The DCA extension can be a lightweight orchestrator that issues NWC requests for each distribution payment, with Lightning.Pub handling the actual settlement.
NIP-78: Application-Specific Data — CONFIG & STATE
Kind: 30078 (addressable, replaceable)
Store DCA configuration as encrypted addressable events:
Also use for client registry, distribution history snapshots, and batch state recovery after restart.
NIP-44: Versioned Encryption — REQUIRED
All financial data (configs, balances, distribution records) encrypted with NIP-44 (ChaCha20 + HMAC-SHA256 + HKDF). Non-negotiable for DCA where amounts and client identities are sensitive.
Supplementary NIPs
Architecture Using NIPs
DCA Distribution Flow:
onNostrEvent()subscriptionpay_keysend(kind 23194) orpay_invoiceWhat's NOT in any NIP:
Recommendation: Use NWC (NIP-47) as the payment primitive, NIP-78 for state, NIP-17 for notifications, NIP-44 for encryption. The DCA scheduling logic lives entirely in the extension — NIPs provide the communication and payment rails.
Superseded by #15
The original DCA approach (SSH polling Lamassu PostgreSQL, hourly cron, separate admin/client extensions) has been redesigned as a Nostr-native Cash Provider system in #15.
Key differences:
The commission calculation logic and proportional distribution math from the original satmachineadmin still apply — they're carried forward into #15's settlement engine.
Keeping this issue open as reference for the original LNbits implementation details and the NIP review comment.