Skip to content

Unilateral Exit

Unilateral exit is the ability to recover all of your funds without Lexe's cooperation, or even if Lexe ceases to exist. This guarantees that your funds can never get stuck in Lexe.

The lexe unilateral-exit command runs a Lightning node on your own machine, closes every one of your channels, and sweeps the funds on-chain. All it needs is your seed phrase and your Google Drive backup.

It is available in the Lexe CLI. To install the CLI, run:

curl -fsSL https://lexe.app/install-cli.sh | bash

What you need

Your seed phrase. The 24 words you saved when you created your wallet. Save them to a file and pass it with --root-seed-path. If you don't have your seed phrase but you do have your backup password, download the password_encrypted_root_seed file from your Google Drive backup and pass it with --password-encrypted-root-seed and --backup-password instead.

Your channel state backup. When you enable Google Drive backup, your node saves its encrypted channel state to a folder named like lexe-prod-mainnet-sgx-763a1b3d... inside X LexeData (DO NOT RENAME, MODIFY, OR DELETE) in your Google Drive. Download these files from drive.google.com:

  • ./channel_manager: one file, holding the state shared by all your channels.
  • channel_monitors/<name>: one file per channel, holding the state needed to close that channel and claim your funds.

You don't need the files under channel_monitors_archive/; those channels' funds have already been claimed.

The downloaded filenames come out mangled (._channel_manager, channel_monitors_<name>); that's fine, just don't rename them yourself. On macOS, the ._channel_manager file is hidden in Finder, and Archive Utility can silently drop it when unzipping. Extract and check your download from a terminal (unzip, ls -a); if the channel manager is missing, download it on its own.

Running it

lexe --root-seed-path ~/seedphrase.txt unilateral-exit \
    --channel-manager ~/Downloads/._channel_manager \
    --monitor ~/Downloads/channel_monitors_<name1> \
    --monitor ~/Downloads/channel_monitors_<name2>

By default, the command optimistically tries to close each channel cooperatively through Lexe's LSP, which settles faster, and force closes whatever the LSP won't cooperate on. A cooperative close isn't truly unilateral, since it needs the LSP to cooperate; it's just an optimization. If the LSP can't be reached at all, every channel is force closed, and your funds come back without Lexe's involvement. The full list of options:

Usage: $ lexe unilateral-exit [OPTIONS]

Options:
      --channel-manager <CHANNEL_MANAGER>
          Path to the encrypted `channel_manager` backup file

      --monitor <MONITORS>
          Path to an encrypted `channel_monitors <name>` backup file.
          Pass once per file.

      --password-encrypted-root-seed <PASSWORD_ENCRYPTED_ROOT_SEED>
          Path to the `password_encrypted_root_seed` backup file.
          An alternative to --root-seed / --root-seed-path.

      --backup-password <BACKUP_PASSWORD>
          The backup password for --password-encrypted-root-seed.
          [env: LEXE_BACKUP_PASSWORD]

      --esplora-urls <ESPLORA_URLS>
          The Esplora URL to sync against.
          Multiple URLs can be specified, separated with commas.
          [default: blockstream.info and mempool.space]

      --force-close-only
          Skip cooperative close; immediately force close all channels

      --coop-close-only
          Only cooperatively close, avoiding the force close
          timelock. Errors out if the LSP won't cooperate.

      --sweep-address <SWEEP_ADDRESS>
          Drain all recovered funds to this address once they've confirmed

      --recovery-dir <RECOVERY_DIR>
          The working dir for the recovery node.
          [default: <LEXE_DATA_DIR>/<env>/<user_pk>/recovery]

  -h, --help
          Print help (see a summary with '-h')

What to expect

A cooperative close settles as soon as its closing transaction confirms. A force close must wait out the channel's contest delay, up to about 4 days, before the funds can be swept. The command may therefore run for a long time, syncing the blockchain and logging progress until every channel's funds are confirmed on-chain, then printing a summary of what it recovered. Recovered funds land in the on-chain wallet derived from your seed phrase, which is the same wallet your Lexe app uses; pass --sweep-address to drain them to another wallet instead.

Progress is saved to the recovery dir as it goes, so the command is safe to interrupt and re-run with the same arguments. Your backup files are imported on the first run, so later runs can omit --channel-manager and --monitor.

If the exit asks for a deposit

A force close transaction has to be fee-bumped before it confirms, which needs a small on-chain balance. If the recovery wallet can't provide it, the exit pauses before closing any channels and prints a deposit address:

ACTION REQUIRED: Force closing your channels requires confirmed on-chain funds
to pay fees, but the recovery wallet can't provide them.
Deposit at least ~1748 sats (suggested: ~11193 sats, since fee-bumps escalate
until your deposit confirms) to:

    bc1q...

Send the suggested amount from any wallet to that address. The exit proceeds on its own once your deposit confirms.

Why this matters

Your private keys live inside a secure enclave that Lexe cannot enter, so Lexe can't spend your funds while your node is running. See How Lexe Works for the details.

Unilateral exit covers the other half of the story: what happens if Lexe goes away, refuses to serve you, or loses your data. The exit runs entirely on your machine, and nothing it depends on is under Lexe's control.

  • Your seed phrase is yours alone.
  • Your channel state backup sits in your own Google account, encrypted under your seed phrase, so neither Lexe nor Google can read it.
  • Blockchain data comes from public servers of your choosing.
  • Lexe's LSP is only ever used to close faster. If it doesn't answer, your channels force close and your funds still come back.

For the full technical security model, see SECURITY.md on GitHub.