pull down to refresh

Who this is for: you run an LND node (Umbrel, Start9, Raspiblitz, or your own) and you want to move onchain sats from your cache/buffer into your Lightning channels: to refill a drained channel, or to fund the channel that pays your "daily driver" mobile wallets.

What we'll use: Lightning Loop, Lightning Labs' non-custodial submarine swap service for LND.

  • loop in = onchain → your LN channels (this is the "refill the SPEND wallet / restore outbound" direction).
  • loop out = your LN channels → onchain (frees inbound liquidity, or sends to cold storage).

Loop is fully non-custodial: your sats are moved through a script-controlled HTLC, no third party can take them. Another valid alternative to Boltz. Consider reading the [Loop CLI manual(https://github.com/lightninglabs/loop/blob/master/docs/loop.md) and learn about Static Loop In Addresses before implementing this guide.


The plan (desktop node option)The plan (desktop node option)

  1. Install and run loopd next to your LND node.
  2. loop in an amount from onchain into your chosen channel.
  3. Move that fresh liquidity over Lightning from your desktop node to your mobile SPEND wallets (pay their invoices).
  4. Optionally loop out when you need inbound capacity or want sats back onchain.
  5. Optionally switch on AutoLoop so it happens by itself.

PrerequisitesPrerequisites


Step 1: Run loopdStep 1: Run loopd

loopd connects to your LND (default localhost:10009, reading ~/.lnd) and exposes its own CLI. On the command line:

loopd

On Umbrel/Start9, just start the Loop app. In Lightning Terminal you can drive everything from the web UI instead of the CLI.

Step 2: Check terms and get a quoteStep 2: Check terms and get a quote

Always quote before swapping: fees move with the mempool.

loop terms

This shows the minimum and maximum amounts for in and out, plus the CLTV delta (how long funds stay locked in a worst-case failed swap).[1]

loop quote in 500000

Gives a fee estimate for a 500,000-sat loop-in: service fee + onchain fee. If you don't like it, wait for lower fees and retry.

Step 3: Loop in (onchain → your channel)Step 3: Loop in (onchain → your channel)

loop in --amt 500000 --last_hop <peer-pubkey> --private --label "refill spend"

Flags explained:

  • --amt: amount in sats (within the min/max from loop terms).
  • --last_hop <pubkey>: force the incoming sats to land in a specific channel (the one to your LSP / daily-driver node).[2] Skip it and Loop picks the best route.
  • --private: important for private nodes: generates route hints so the Loop server can route the payment to you even though your channels aren't announced.
  • --label: your own note ("refill spend", "august top-up", whatever).

Loop now prints one (or two) onchain HTLC addresses. Send the exact amount to that address:

  • From your node's onchain wallet (default): just confirm, it pays itself.
  • From an external cache wallet (exchange, Electrum, Sparrow, cold storage): use --external when you start the swap, then send the exact amount from that wallet to the address Loop printed.

Once your onchain transaction confirms, the Loop server pays you the sats over Lightning into your channel. That channel now has outbound liquidity again.

Step 4: Watch it completeStep 4: Watch it complete

loop monitor

or

loop listswaps

Both show in-flight and past swaps with their state, fees, and any failure reason.

Step 5: Move the liquidity to your SPEND walletsStep 5: Move the liquidity to your SPEND wallets

The point of Loop here: the fresh sats now sit in your desktop node. To actually refill your mobile SPEND wallet:

  1. Open your mobile wallet (Zeus / Blixt / Lightning Pub), tap Receive, create an invoice for the amount (e.g. 210,000 sats).
  2. Pay that invoice from the desktop node: via the lncli payinvoice command, or the node's web UI (ThunderHub / RTL / Lightning Terminal "Send").
  3. Sats arrive on your phone in seconds.

The desktop node + Loop is your buffer; the mobile wallets are your spending front-ends.


The reverse: loop out (LN → onchain)The reverse: loop out (LN → onchain)

Use this to free inbound liquidity (so you can receive again), or to move sats to your cache/cold wallet without closing channels:

loop out 250000 --addr bc1q... --conf_target 144 --label "to cache"
  • --addr: where the onchain sats go (default: your node's wallet).
  • --channel <short-channel-id>: drain a specific channel.
  • --fast: instant loop out (skips batching, pays more).
  • --conf_target: high number (e.g. 144) = slower, cheaper sweep; low = fast, pricey.
  • --max_swap_routing_fee: cap the offchain routing fee.

Optional: automate with AutoLoopOptional: automate with AutoLoop

Once you're comfortable, let Loop keep you balanced on its own:

loop setparams --autoloop=true --easyautoloop=true --localbalancesat=1000000

Or per channel (refill a channel whenever its outbound drops below 25%):

loop setrule <channel-id> --outgoing_threshold=25 --incoming_threshold=25

Advanced: static loop-in addresses (pre-fund during low fees)Advanced: static loop-in addresses (pre-fund during low fees)

Loop v0.27+ lets you create a permanent taproot address that you can fund onchain at any time: even months ahead: and execute the actual swap later:

loop static new          # create your static address
loop static summary      # see it
  • Send onchain sats to that address whenever fees are low (the deposit expires after ~3 months).[3]
  • Later, swap it into your channels: loop static in --amt ... (or --all).
  • It doubles as a normal onchain wallet: loop static withdraw <address> <amt>.
  • Guard your L402 token in ~/.loop/<network>/: if you lose it, unspent deposits are stuck until the timeout expires.[4]

Newer versions can also open a channel directly from static deposits: loop openchannel.


Gotchas & notesGotchas & notes

  • Check loop terms for min/max: loop-out minimum is often ~250,000 sats and can rise in high-fee periods.
  • Loop In needs inbound capacity to receive the Lightning payment. If the target channel is already full on your side, loop-out first (or pick another channel).
  • Fees vary a lot with the mempool. Always loop quote first; during low-fee weekends a 500k swap can cost ~2-3k sats total, during spikes it can be far more.
  • Loop requires LND built with all subservers; if swaps fail at startup with a subserver error, that's why.
  • loopd has its own macaroon/TLS (~/.loop), separate from LND's: don't mix them up.
  • Loop works with Neutrino, Bitcoin Core and btcd backends.

Cost check (rough, mainnet, 2026)Cost check (rough, mainnet, 2026)

  • Loop service fee: ~0.05–1% (in/out differ; quoted up-front).
  • Onchain miner fee: funding tx (in) or sweep tx (out): the biggest variable.
  • Lightning routing fee: capped via --max_swap_routing_fee.
  • No Boltz, no exchange withdrawal fee, no channel closes.

Note: This guide may contain inaccurate information as technology evolve and tooling tune up. Feel free to report any inaccurancy in the comments below.

  1. The CLTV delta is how many blocks your sats stay locked in the HTLC if a loop-in can't be completed (e.g. no inbound capacity): worst case you wait it out; you don't lose them. See The Loop CLI.

  2. Loop In delivers the incoming sats to you as a Lightning payment, so the channel it lands in needs inbound capacity (which a drained spend channel naturally has). --last_hop <pubkey> pins the payment to one specific channel, identified by the peer's node pubkey. See The Loop CLI.

  3. Static addresses are 2-of-2 taproot addresses (one key yours, one Loop's); deposits expire after ~14,400 blocks (~100 days), and you can withdraw from them at any time. See Static Loop In Addresses.

  4. Loop authenticates with L402s (LSAT); the token lives in ~/.loop/<network>. If you lose it, unspent static-address deposits can't be swapped until the timeout passes. See Static Loop In Addresses.

I would recommend using static addresses if you're running a node with an active LOOP channel, and want to automate refilling it's liquidity.

reply

That's a great point and useful suggestion. But wouldn't be risky to use a static address? As loop static new gives a permanent on-chain deposit address (2-of-2 taproot: one key yours, one Loop's). This is a pre-funding box, not an actual swap. From my innerstanding, the flow would work like this:

  • Send onchain sats to it any time, in any amount, in multiple deposits, especially during a low-fee period. Channels aren't touched yet.
  • Later, loop static in --all converts those confirmed deposits into channel balance instantly (no waiting on a new onchain tx to confirm).
  • Deposits expire after ~14,400 blocks (~100 days) and are withdrawable anytime; the swap needs your L402 token in ~/.loop.

The other point you mention is about automaticly refill channel liquidity, I found two ways to do it:

  1. Automate the funding by keeping the address pre-filled: exchange auto-withdraw to the static address, or a cron/systemd job that sweeps your cache wallet when feerate is below a threshold (buy deposits when the mempool is quiet).
  2. Automate the swap using loopd to refill the channel itself, funded from those deposits:
    loopd --experimental
    loop setparams --autoloop=true --type=in --loopinsource=static-address
    loop setrule <channel-id> --outgoing_threshold=30
    loop setparams --autobudget=100000 --autobudgetrefreshperiod=604800s

Now whenever a channel's outbound liquidity drops below your threshold, loopd should fire a loop-in automatically from the static deposits. --loopinsource=static-address is the piece that ties them together.

Note: This is currently an experimental feature, use at your own risk.

@AuthenticityBTC how else would you do it?

reply

Yes, there is risk if they go offline or their key acts maliciously your funds may be locked until the HTLC timeout (14400 blocks). But, the protection it gives me in busy periods is valuable enough - as having LOOP close during a busy period can be an expensive loss of liquidity while waiting for the channel to refill (naturally and rebalancing). I keep a safety amount in my static address for these busy periods.

There are periods when I have a full 500M drain on my channel.

I use custom code for managing my static loop in. I have not looked at the loopd automation at this time.

reply
Part of a series responding to How to refill your emptied LN channels without Boltz swaps and provide more guidance on each option. One guide per method: Electrum, Loop, Phoenix / phoenixd, RoboSats / friend.

Read Managing LN wallets liquidity first if you haven't.

reply