Lightning Network Wallet Development
Lightning Network is a payment channel network on top of Bitcoin that enables payments in milliseconds with fees in fractions of satoshi. Idea is simple: two participants lock BTC in multisig on-chain, then exchange signed balance states off-chain unlimited times. On-chain transaction only on channel open/close. In practice — a graph of millions of channels with payments routed through intermediate nodes.
Developing Lightning wallet is fundamentally different task compared to regular Bitcoin or EVM wallet. There's no simple "sign transaction and send." Need to manage channel state, monitor on-chain events, process routing, store secrets (preimages). Errors in state management can lead to fund loss.
Lightning Wallet Architecture
Lightning wallet fundamentally divides into two classes: custodial and non-custodial. Choice determines entire architecture.
Custodial Wallet
User doesn't hold keys to channels. Server (provider) manages channels, user sees balance and sends payments via API. Examples: Strike, CashApp, Wallet of Satoshi.
Pros: simple client implementation, no channel management problems, user doesn't need to be online. Cons: custodial risk, regulatory questions, user trusts provider.
Custodial Lightning is essentially API wrapper over LND or CLN node. Client app works with balances in service database, real Lightning channels only at provider.
Non-custodial: Embedded Node
User holds keys, node runs directly in app. Two approaches:
LDK (Lightning Development Kit) — library from Spiral (former Square Crypto). Rust-core with bindings for Swift, Kotlin, Python, JavaScript (via WASM). Maximum flexibility: app decides what to store, how to store, where to get blockchain data from. Used in apps like Phoenix (partially), Mutiny Wallet.
Breez SDK — higher-level, uses Greenlight under hood. Greenlight from Blockstream — scheme where user holds keys but node runs in Blockstream cloud. Developer doesn't manage node at all — only SDK methods.
Deep Dive: Payment Channel State Machine
Understanding channel state machine is critical for any serious implementation. Simple model shown.
Commitment transaction — transaction signed by both sides, either can publish on-chain anytime, closing channel. At any moment only one valid commitment transaction exists for each side (each side has own version with asymmetric timelock).
Why asymmetric? If Alice publishes commitment transaction, she can't spend her output immediately — OP_CHECKSEQUENCEVERIFY (CSV) delay (e.g., 144 blocks). Bob can spend his output immediately. This gives Bob time to react if Alice published old (revoked) commitment — he can take entire channel balance via penalty transaction.
Key secret — commitment revocation key. With each state update sides exchange per_commitment_secret of previous state. Having this secret, opposite side can if needed build penalty transaction to punish cheater.
State 0: Alice 1 BTC, Bob 0 BTC -> Alice reveals secret_0 to Bob
State 1: Alice 0.5 BTC, Bob 0.5 -> Bob reveals secret_1 to Alice
State 2: Alice 0.3 BTC, Bob 0.7 -> Alice reveals secret_2 to Bob
If Alice tries to publish State 0 (more favorable to her), Bob already has secret_0 and can apply penalty, taking all of Alice's balance. This economic incentive prevents cheating.
HTLC: Routing Through Intermediaries
For payments through intermediate nodes use HTLC (Hash Time-Locked Contract). Payment from Alice to Carol through Bob:
- Carol generates random preimage
R, gives Alicehash(R)in invoice - Alice adds HTLC to Bob's channel: "give Bob X satoshi if he shows preimage for
hash(R)until block N" - Bob adds similar HTLC to Carol's channel (slightly less satoshi — his fee, slightly smaller timeout)
- Carol reveals preimage to Bob, takes payment
- Bob reveals preimage to Alice, takes payment
If something goes wrong — HTLC expires by timeout, funds return. Bob learned preimage only when Carol revealed it — he couldn't cheat earlier.
In code implementation (LDK) this looks like series of event callbacks:
fn handle_event(&self, event: Event) {
match event {
Event::PaymentClaimable { payment_hash, amount_msat, .. } => {
// We receive incoming payment, need preimage
if let Some(preimage) = self.pending_payments.get(&payment_hash) {
self.channel_manager.claim_funds(*preimage);
}
}
Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
// Payment successfully received
}
Event::PaymentFailed { payment_hash, .. } => {
// Payment failed, update UI
}
_ => {}
}
}
Watchtower: Protecting Offline Users
Non-custodial Lightning has fundamental problem: if user is offline and counterparty publishes old commitment transaction — user can lose funds (CSV timelock window). Solution — watchtower.
Watchtower is service that wallet delegates to for blockchain monitoring. Algorithm:
- With each channel state update wallet sends watchtower encrypted blob (penalty transaction + decryption key, encrypted with txid of revoked commitment)
- Watchtower monitors blockchain
- If sees fraudulent commitment — decrypts blob, publishes penalty transaction
- Watchtower takes share of penalty (usually 1%) as reward
In LDK: channel_manager.get_relevant_txids() returns txids to watch. Data for watchtower generated by channel_monitor.get_latest_holder_commitment_txn().
Open protocols: BOLT 13 (draft). Real implementations: The Eye of Satoshi (TEOS), Lightning Rod (Zeus). Can integrate ready watchtower or run own.
BOLT 12: Offers Protocol
BOLT 11 invoice — single-use. Can't reuse, no recurring payment support. BOLT 12 Offers — new standard (already in CLN, in development for LND):
- Offer — permanent code, like payment address. Can publish on site, accept recurring payments
- Refund — analog for refunds
- Built-in recurring payment support
- Onion messaging for invoice exchange without on-chain operations
For new wallet with eye on e-commerce integration — should add BOLT 12 immediately. CLN supports fully. LDK — actively developing.
Channel Management: Submarine Swaps and Liquidity
One of main Lightning UX problems — inbound liquidity. To receive payments, need incoming liquidity in channels. For new wallet without channels — this is problem.
Submarine Swap — atomic exchange of on-chain BTC for off-chain Lightning BTC (and back). Used for:
- Funding wallet via on-chain transaction with automatic channel opening
- Withdrawing funds from Lightning to on-chain address
Protocols: Loop (Lightning Labs), Boltz Exchange. Integration via their API or deploying own swap server.
LSP (Lightning Service Provider) — liquidity provider. On first payment to wallet LSP automatically opens channel with needed incoming liquidity. Standard: LSPS0/LSPS1/LSPS2. Phoenix uses exactly this model.
Stack and Technologies
| Component | Technology | Application |
|---|---|---|
| Lightning core | LDK (Rust/bindings) | Non-custodial mobile |
| Hosted node | Greenlight + Breez SDK | Managed non-custodial |
| Lightning node | LND (Go) / CLN (C) | Custodial / server |
| On-chain data | Electrum protocol / Esplora | Synchronization |
| Watchtower | TEOS / custom | Offline protection |
| Submarine swaps | Boltz API | On/off-ramp |
| Mobile | React Native + LDK bindings | iOS + Android |
What's Important During Development
Persisting channel state — critical. Loss of channel monitor state can lead to fund loss or inability to close channel correctly. LDK requires reliable Persist trait implementation — every state update must be written before confirming to counterparty.
Fee management — HTLC routing fee and on-chain fee on channel open/close. User should understand fee structure. For custodial wallets — can absorb routing fee.
Invoice expiry — BOLT 11 invoice has expiry (default 3600 seconds). UI should show remaining time and be able to generate new invoice.
Timeline
Custodial Lightning wallet (mobile app + backend on LND/CLN): 6-8 weeks.
Non-custodial with Breez SDK (simplified non-custodial): 8-10 weeks — SDK hides most complexity.
Full non-custodial implementation on LDK with watchtower, LSP integration, BOLT 12, submarine swaps: 4-6 months. Production-grade product level Phoenix or Mutiny.
Secure channel state management requires special attention and code review from specialists experienced in Lightning protocol.







