Skip to main content

Lightning Network Integration

SatSigner provides seamless integration with the Lightning Network through LND (Lightning Network Daemon) connectivity. Connect your existing LND node to send and receive instant, low-fee Bitcoin payments.

Overview

The Lightning integration allows you to:
  • Connect to remote LND nodes via REST API
  • Monitor node status, channels, and peers in real-time
  • Create and decode Lightning invoices
  • Send payments through the Lightning Network
  • View channel balances and liquidity
  • Track payment history and preimages

LND REST API Connection

Connection Methods

SatSigner supports connecting to LND nodes through the REST API interface: LND REST (Currently Available)
  • Uses macaroon-based authentication
  • Supports remote connections over HTTPS
  • Requires connection string in format: config=https://your-node.com/config.json
Coming Soon
  • LND RCP: Direct gRPC connection for lower latency
  • LDK: Embedded Lightning node running directly in the app

Connection Configuration

The connection string points to a JSON configuration file containing:
{
  "configurations": [
    {
      "macaroon": "<hex-encoded-macaroon>",
      "cert": "<optional-tls-cert>",
      "uri": "https://your-node.com:8080"
    }
  ]
}
Required Fields:
  • macaroon: Hex-encoded admin or invoice macaroon for authentication
  • uri: REST API endpoint URL of your LND node
  • cert: (Optional) TLS certificate for self-signed certificates

Setting Up Your Connection

Step 1: Prepare Your LND Node

  1. Ensure your LND node has REST API enabled
  2. Generate an admin or invoice macaroon
  3. Create a configuration JSON file with your node details
  4. Host the config file on a secure HTTPS endpoint

Step 2: Connect in SatSigner

  1. Navigate to Lightning from the main menu
  2. Tap LND Rest to initiate connection
  3. Either:
    • Scan QR Code: Scan your config QR code
    • Paste: Paste your connection string (config=https://...)
  4. Tap Connect to Node

Step 3: Verify Connection

Once connected, SatSigner will:
// Fetch node information from /v1/getinfo endpoint
const response = await fetch(`${config.url}/v1/getinfo`, {
  headers: {
    'Grpc-Metadata-macaroon': config.macaroon,
    'Content-Type': 'application/json'
  }
})
You’ll see your node information displayed:
  • Node alias and public key
  • Connection status (Connected/Disconnected)
  • Number of active channels
  • Number of connected peers
  • Chain synchronization status
  • Block height

Node Management

Viewing Node Information

Access comprehensive node details:
type LNDNodeInfo = {
  version: string                // LND version
  commit_hash: string            // Git commit hash
  identity_pubkey: string        // Node public key
  alias: string                  // Node alias
  num_active_channels: number    // Active channel count
  num_peers: number              // Connected peers
  block_height: number           // Current block height
  block_hash: string             // Latest block hash
  best_header_timestamp: string  // Latest block timestamp
  synced_to_chain: boolean       // Sync status
  chains: string[]               // Connected chains
  uris: string[]                 // Node URIs
}

Channel Management

Monitor your Lightning channels:
type LNDChannel = {
  active: boolean                // Channel active status
  remote_pubkey: string          // Peer public key
  channel_point: string          // Funding transaction
  chan_id: string                // Channel ID
  capacity: number               // Total capacity (sats)
  local_balance: number          // Your balance (sats)
  remote_balance: number         // Peer balance (sats)
  commit_fee: number             // Commitment fee
  unsettled_balance: number      // Pending HTLCs
  total_satoshis_sent: number    // Lifetime sent
  total_satoshis_received: number // Lifetime received
  num_updates: number            // State updates
  private: boolean               // Private channel
  initiator: boolean             // You opened channel
  lifetime: number               // Channel age (seconds)
  uptime: number                 // Uptime (seconds)
}

Creating Lightning Invoices

Generate invoices for receiving payments:
// Create invoice via /v1/invoices endpoint
const invoice = await createInvoice(
  amount,      // Amount in satoshis
  description  // Invoice memo
)
Invoice includes:
  • Payment request (bolt11 invoice string)
  • Payment hash
  • Expiration time
  • Amount and description

Sending Lightning Payments

Payment Flow

  1. Decode Invoice: Parse bolt11 payment request
type LNDecodedInvoice = {
  payment_request: string   // Original invoice
  value: string            // Amount (sats)
  description: string      // Payment memo
  timestamp: string        // Creation time
  expiry: string          // Expiration
  payment_hash: string    // Payment identifier
  payment_addr: string    // Payment address
  num_satoshis: string    // Amount in satoshis
  num_msat: string        // Amount in millisats
  payment_secret: string  // Payment secret
  min_final_cltv_expiry: string // CLTV delta
}
  1. Send Payment: Execute payment via /v1/channels/transactions
const payment = await payInvoice(paymentRequest)
  1. Poll for Status: Check payment completion
// Poll /v1/payments/{payment_hash} until status is SUCCEEDED or FAILED
while (attempts < maxAttempts) {
  const status = await checkPaymentStatus(payment_hash)
  if (status === 'SUCCEEDED') break
  if (status === 'FAILED') throw new Error('Payment failed')
  await sleep(1000) // Wait 1 second
}
Payment Response:
type LNDPaymentResponse = {
  payment_hash: string      // Payment identifier
  payment_preimage: string  // Proof of payment
  status: string           // SUCCEEDED | FAILED | IN_FLIGHT
}

Connection Persistence

SatSigner stores your LND configuration securely:
type LNDConfig = {
  macaroon: string  // Hex-encoded macaroon
  cert: string      // TLS certificate
  url: string       // REST API endpoint
}
State Management:
  • Configuration persisted to secure storage (MMKV)
  • Connection status monitored every 30 seconds
  • Automatic reconnection on network changes
  • Node info and channels cached locally

API Endpoints Used

SatSigner interacts with these LND REST endpoints:
EndpointMethodPurpose
/v1/getinfoGETFetch node information
/v1/balance/blockchainGETGet on-chain balance
/v1/channelsGETList channels
/v1/invoicesPOSTCreate invoice
/v1/channels/transactionsPOSTSend payment
/v1/payments/{hash}GETCheck payment status
Authentication Header:
Grpc-Metadata-macaroon: <hex-encoded-macaroon>

Security Considerations

Macaroon Security

  • Never share your admin macaroon publicly
  • Use invoice-only macaroons for receiving payments
  • Use read-only macaroons for monitoring
  • Rotate macaroons periodically

Network Security

  • Always use HTTPS for remote connections
  • Verify TLS certificates when possible
  • Consider using Tor for additional privacy
  • Keep connection strings secure

Backup Best Practices

  • Backup your LND seed phrase separately
  • Store channel backups (SCB files) securely
  • Document your node configuration
  • Test recovery procedures

Troubleshooting

Connection Issues

“Failed to connect to LND node”
  • Verify REST API is enabled on your LND node
  • Check firewall rules allow connections
  • Confirm macaroon has required permissions
  • Test endpoint URL in a browser
“Invalid config format”
  • Ensure JSON is properly formatted
  • Verify all required fields are present
  • Check connection string format: config=https://...

Payment Failures

“No route found”
  • Insufficient inbound/outbound liquidity
  • Recipient not reachable
  • Try increasing max fee or CLTV delta
“Payment timeout”
  • Network congestion
  • Offline routing nodes
  • Try again with different route hints

Advanced Features

Custom Request Handler

For advanced users, SatSigner exposes a generic request handler:
const makeRequest = async <T>(
  endpoint: string,
  options?: LNDRequestOptions
) => Promise<T>
Example Usage:
// Get pending channels
const pending = await makeRequest('/v1/channels/pending')

// Close channel
await makeRequest('/v1/channels/${channelPoint}', {
  method: 'DELETE',
  body: { force: false }
})

Implementation Reference

Core Hook: apps/mobile/hooks/useLND.ts:1 Connection Setup: apps/mobile/app/(authenticated)/(tabs)/(signer,explorer,converter)/signer/lightning/LNDRest/index.tsx:29 State Management: apps/mobile/store/lightning.ts:1 Type Definitions: apps/mobile/types/models/LND.ts:1

Future Enhancements

Upcoming Lightning features:
  • LDK Integration: Embedded Lightning node
  • LNURL Support: LNURL-pay and LNURL-withdraw
  • Keysend Payments: Spontaneous payments without invoices
  • Multi-path Payments: Split payments across multiple routes
  • Channel Rebalancing: Automated liquidity management
  • Submarine Swaps: On-chain to Lightning swaps

Resources

Build docs developers (and LLMs) love