Lightning Beginner 6 min read
Lightning Wallets
Lightning wallet options for agents. Self-custody vs custodial, API access, and wallet selection criteria.
wallets custody mobile api lnbits
Lightning Wallets
A Lightning wallet manages your channels and enables payments. For agents, wallet selection determines API access, custody model, and operational complexity.
Wallet Selection Criteria
| Factor | Question |
|---|---|
| Custody | Do you control the keys? |
| API access | Can agents interact programmatically? |
| Liquidity | How do you get inbound capacity? |
| Uptime | What happens when wallet is offline? |
| Cost | Setup and operational costs? |
Agent-Friendly Wallets
LNbits
Type: Self-hosted wallet manager Best for: Agents needing simple REST API
import requests
LNBITS_URL = "https://your-lnbits.com"
API_KEY = "your-invoice-key"
# Create invoice
response = requests.post(
f"{LNBITS_URL}/api/v1/payments",
headers={"X-Api-Key": API_KEY},
json={"out": False, "amount": 1000, "memo": "Agent payment"}
)
invoice = response.json()["payment_request"]
# Pay invoice
response = requests.post(
f"{LNBITS_URL}/api/v1/payments",
headers={"X-Api-Key": ADMIN_KEY}, # Admin key for sending
json={"out": True, "bolt11": "lnbc..."}
)
Pros:
- Simple REST API
- Multiple wallets from one node
- Extensions (LNURL, PoS, etc.)
- Can use shared instances
Cons:
- Requires underlying node
- Shared instances = custody risk
Alby
Type: Browser extension + API Best for: Web integrations, Lightning Address
// Alby API
const response = await fetch('https://api.getalby.com/invoices', {
method: 'POST',
headers: {
'Authorization': `Bearer ${ALBY_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 1000,
description: 'Agent payment'
})
});
const { payment_request } = await response.json();
Pros:
- Lightning Address (you@getalby.com)
- OAuth for user wallets
- NWC (Nostr Wallet Connect)
Cons:
- Custodial by default
- Rate limits on free tier
Phoenix
Type: Mobile self-custody Best for: Personal use, not agents
Pros:
- True self-custody
- Automatic channel management
- Swap in/out
Cons:
- No server API
- Mobile only
- LSP dependent
Wallet of Satoshi
Type: Custodial mobile Best for: Quick testing
Cons:
- Fully custodial
- No API
- KYC in some regions
Wallet Comparison
| Wallet | Custody | API | Agent Use | Setup |
|---|---|---|---|---|
| LNbits | Self* | REST | ⭐⭐⭐⭐⭐ | Medium |
| Alby | Custodial | REST | ⭐⭐⭐⭐ | Easy |
| LND | Self | gRPC | ⭐⭐⭐⭐⭐ | Hard |
| Core Lightning | Self | JSON-RPC | ⭐⭐⭐⭐⭐ | Hard |
| Phoenix | Self | None | ⭐ | Easy |
| Breez | Self | SDK | ⭐⭐⭐ | Medium |
| Mutiny | Self | WASM | ⭐⭐ | Easy |
*LNbits is as custodial as the underlying node
Setting Up LNbits
Using Public Instance (Testing Only)
# legend.lnbits.com - DO NOT USE FOR REAL FUNDS
LNBITS_URL = "https://legend.lnbits.com"
Self-Hosted (Recommended)
# Docker setup
git clone https://github.com/lnbits/lnbits.git
cd lnbits
cp .env.example .env
# Edit .env with your settings
docker-compose up -d
Connect to Your Node
# .env for LNbits
LNBITS_BACKEND_WALLET_CLASS=LndRestWallet
LND_REST_ENDPOINT=https://your-lnd:8080
LND_REST_CERT=/path/to/tls.cert
LND_REST_MACAROON=your-admin-macaroon-hex
API Patterns
Invoice Polling
def wait_for_payment(payment_hash, timeout=300):
"""Poll until invoice is paid or timeout."""
start = time.time()
while time.time() - start < timeout:
response = requests.get(
f"{LNBITS_URL}/api/v1/payments/{payment_hash}",
headers={"X-Api-Key": API_KEY}
)
status = response.json()
if status["paid"]:
return True
time.sleep(5)
return False
Webhook Notifications
# LNbits supports webhooks
invoice = requests.post(
f"{LNBITS_URL}/api/v1/payments",
headers={"X-Api-Key": API_KEY},
json={
"out": False,
"amount": 1000,
"memo": "Webhook test",
"webhook": "https://your-server.com/lnbits-webhook"
}
)
Balance Monitoring
def get_balance():
response = requests.get(
f"{LNBITS_URL}/api/v1/wallet",
headers={"X-Api-Key": API_KEY}
)
return response.json()["balance"] // 1000 # msat to sats
Key Management
LNbits Keys
| Key Type | Permission | Use Case |
|---|---|---|
| Invoice key | Create invoices, check status | Receiving |
| Admin key | Send payments, full access | All operations |
Security: Never expose admin key in client-side code.
Multi-Wallet Setup
# Create separate wallets for different purposes
wallets = {
"receiving": {"url": LNBITS_URL, "key": INVOICE_KEY_1},
"sending": {"url": LNBITS_URL, "key": ADMIN_KEY_1},
"savings": {"url": LNBITS_URL, "key": INVOICE_KEY_2}
}
Wallet Security
For Agents
- Separate wallets: Don’t mix agent funds with personal
- Limited balances: Keep minimum needed for operations
- Admin key protection: Store securely, rotate regularly
- Monitoring: Alert on unexpected balance changes
Backup Strategies
| Wallet Type | Backup Method |
|---|---|
| LND | channel.backup (SCB) |
| Core Lightning | hsm_secret + database |
| LNbits | Database export |
| Mobile | Seed phrase |
Choosing a Wallet
Decision Tree
Need API access?
├── No → Phoenix, Mutiny (personal use)
└── Yes
├── Have your own node?
│ ├── Yes → LNbits self-hosted
│ └── No
│ ├── Trust a provider? → LNbits shared, Alby
│ └── No → Set up a node first
└── Just testing? → legend.lnbits.com (small amounts)
Related Topics
- Node Types - Underlying infrastructure
- API: LNbits - Full API reference
- Security - Wallet security practices
- LSPs - Liquidity for wallets
Machine-Readable Summary
{
"topic": "lightning-wallets",
"agent_recommended": [
{
"name": "lnbits",
"custody": "self",
"api": "rest",
"setup": "medium"
},
{
"name": "alby",
"custody": "custodial",
"api": "rest",
"setup": "easy"
}
],
"api_patterns": [
"create_invoice",
"pay_invoice",
"check_balance",
"webhook_notifications"
]
}