Skip to content

Python Quickstart

The Lexe Python SDK provides a simple interface that makes it easy to integrate a self-custodial Lightning wallet into any Python application, or create and manage a wallet interactively via a Python REPL.

Install

pip install lexe-sdk

Python 3.10+ is required. Prebuilt wheels are available for Linux (x86_64, aarch64), macOS (x86_64, Apple Silicon), and Windows (x86_64).

Try out the Lexe SDK in a REPL (no install required)

All code examples below are runnable. If you use uv, you can launch a Python REPL with the Lexe SDK available in scope as lexe:

uv run --with lexe-sdk python

Configure credentials

The Python SDK authenticates with one of the following:

  1. Client credentials: scoped and revocable, well-suited for controlling your own existing wallet, or for building applications with limited access to other people's wallets, including charging for services via pull payments.
  2. Root seed: the master secret of a Lexe wallet, used to create new wallets.

See the Authentication page for more details.

Control an existing wallet (client credentials)

Get client credentials from the Lexe mobile app

  1. Download the Lexe mobile app (iOS, Android)
  2. Menu > "Client credentials" > "Create credentials"
  3. Copy the credentials string

If you're running a service which helps manage your users' wallets, you can collect your users' client credentials using a web form or similar.

Set LEXE_CLIENT_CREDENTIALS in your environment

export LEXE_CLIENT_CREDENTIALS="eyJsZXhlX2F1dGhfdG9rZ...TA0In0"

A .env file loaded with python-dotenv or uv run --env-file .env is also common.

Runnable example: Instantiating a LexeWallet from client credentials.

import os

from lexe import ClientCredentials, Credentials, LexeWallet, WalletConfig

config = WalletConfig.mainnet()
cc = ClientCredentials.from_string(os.environ["LEXE_CLIENT_CREDENTIALS"])
creds = Credentials.from_client_credentials(cc)
wallet = LexeWallet.load_or_fresh(config, creds)

# Ensure the node is running the latest enclave version
wallet.provision(creds)

Create a new wallet (root seed)

Generate a fresh RootSeed, sign up with Lexe, and provision a Lightning node. The seed is persisted to ~/.lexe/seedphrase.txt and auto-loaded on subsequent runs.

Runnable example: Instantiating a LexeWallet from a root seed.

from lexe import Credentials, LexeWallet, RootSeed, SeedFileError, WalletConfig

# Create a wallet config for mainnet (or testnet3() for testing)
config = WalletConfig.mainnet()

# Try to load an existing seed from ~/.lexe, or create a fresh one
try:
    seed = RootSeed.read(config)
    is_new_seed = False
except SeedFileError.NotFound:
    seed = RootSeed.generate()
    is_new_seed = True

# Create credentials and load or create wallet (data stored in ~/.lexe)
creds = Credentials.from_root_seed(seed)
wallet = LexeWallet.load_or_fresh(config, creds)

if is_new_seed:
    # Sign up the user and provision their node.
    # Pass your partner_user_pk to associate the node with your platform.
    wallet.signup(
        root_seed=seed,
        partner_pk=None,  # Your partner user_pk (hex), if applicable
    )

    # Persist the seed so we can load it on subsequent runs.
    # Stored at ~/.lexe/seedphrase.txt (mainnet).
    seed.write(config)
else:
    # Ensure the node is running the latest enclave version
    wallet.provision(creds)

Using the LexeWallet

Continuing from either example above, you can use the wallet instance to create invoices, send payments, and more:

Runnable example: Common LexeWallet operations.

from lexe import PaymentFilter

# Get node info
info = wallet.node_info()
print(f"Balance: {info.balance_sats} sats")

# Create a Lightning invoice
resp = wallet.create_invoice(
    expiration_secs=3600,
    amount_sats=5000,
    description="Initial deposit",
)
print(f"Invoice: {resp.invoice}")

# Pay a Lightning invoice
wallet.pay_invoice(
    invoice="lnbc...",
    fallback_amount_sats=None,
    personal_note="Open-source donation",
)

# Sync and list payments
wallet.sync_payments()
payments = wallet.list_payments(filter=PaymentFilter.ALL)
for p in payments.payments:
    print(f"  {p.status}: {p.amount_sats} sats")