Building A Bitcoin Bank That Supports Lightning Payments

Bitcoin bank home page

In my previous Bitcoin bank article, I explained the concepts I used in building a simple Bitcoin bank, click on this link to read the previous article.

The Bitcoin bank project has been extended to support Lightning payments, this article covers the concepts I used for my Lightning payments functionality.


  • A running Bitcoin Core node on Signet or Tesnet network
  • A running Lightning node (LND precisely)
  • Nodejs installed a minimum of version 14.19.0
  • PostgresDB installed
  • Typescript experience
  • Bitcoin development knowledge

Lightning Network

Lightning Network is a Bitcoin layer 2 solution that provides faster and cheaper transactions than Bitcoin on-chain transactions, Lightning scales Bitcoin without trading off decentralization, unlike scaling solutions like block size increase which will lead to centralization.

Bitcoin bank users will benefit from a Lightning integration because they will be able to make micro-bitcoin payments, and their payments will be processed and settled way faster than Bitcoin on-chain transactions that take some time before they get confirmed.

You can read more about Lightning Network in this article:

Bitcoin bank Lightning invoice generation page

How It Works

  • The Lightning payment functionality is built using a local Lightning node that has an open channel, LND was my preferred Lightning node implementation for this project
  • The backend server connects to LND using grpc, the grpc library used in this project is @radar/lnrpc, because it works well with Typescript.
  • When the user hits api/v1/lightning/invoice API endpoint the server request for a new BOLT 11 invoice from the LND node using lncli add invoice command
// Lncli add new invoice commandlncli addinvoice {amountInSats}
  • After successfully adding the invoice the backend server subscribes to the newly created invoice to watch for payments
  • If payment is made successfully and settled the payment value in sats is converted to bitcoins and added to the user’s balance

Note: The invoice payment value in sats is converted to bitcoins in this project because I wanted users to have a single wallet balance for Bitcoin transactions and Lightning payments.

// Convert sats to bitcoinsconst satsToBtc: number = sats / 100000000// The sats is divided by 100 million because 100 million satoshis make 1 bitcoin. 
  • A user can as well make an outbound Lightning payment by pasting the BOLT 11 invoice payment request, if the user has enough balance to pay the invoice amount and also routing fees, the payment will be processed successfully

Invoice creation code

Subscribe to invoice code

How the subscribeToInvoice function works

  • When the subscribeToInvoice function is called it adds the invoice to a user’s transaction log sets the transaction type as receive, and the status to 0 (i.e the transaction has not yet been settled)
  • After adding the transaction to the logs, it subscribes and watches for payments that will be sent to the invoice
  • If a successful payment is made that returns a positive settled response, it updates the transaction status in the transaction logs to 1 (i.e the transaction is settled) and adds the amount to the user’s balance

Note: In this project, a custodial Lightning wallet approach is being used, which means users don’t have to open a payment channel, they don’t have to create a payment route for their transactions, and they don’t have access to their wallets.

Users have to put their trust in the bank to help process their transactions and give them a summary of their balance and transactions they have made.

A lightning user can choose to go for a hosted channel if they want a bit more control, you can read more about hosted channels here.

You can get the full code on Github here.

How to Run

Read project

Server .env variables

PORT = 5001 // Server portRPC_USER= // Bitcoin node rpc usernameRPC_PASS= // Bitcoin node rpc password
RPC_PORT=18443 // Bitcoin node rpc port
RPC_URL='' // Bitcoin node urlDEV_DB_USER = ''
// Postgresdb database username
DEV_DB_PASS = '' // Postgresdb database password
DEV_DB_NAME = '' // Postgresdb database name
TOKEN_SECRET = '' // Jsonwebtoken secret keyHOT_WALLET_NAME=hotwallet // Name for the bitcoin hot wallet
COLD_WALLET_NAME=coldwallet // Name for the bitcoin cold wallet
TRANS_FEE = 0.00000200 // Base transaction fee incase u can't estimate the last transaction fee
FEE_PERCENT = 1 // The transaction fee the bank takes for outbound transactions
NO_OF_CONFIRMATIONS = 6 // No of transaction confirmations before adding transaction value to a users' balance
# lnd
LND_MACROON_PATH = '' // LND admin macroon path
LND_TLS_PATH = '' // LND TLS path
LND_RPC_URL = 'localhost:${portNumber}' // LND rpc url

Lightning API Routes

  • POST /api/v1/lightning/invoice = Create inbound Lightning BOLT 11 invoice
  • GET /api/v1/lightning/payments = List user’s Lightning payments
  • POST /api/v1/lightning/lookup = Lookup Lightning invoice
  • POST /api/v1/lightning/pay = Pay outbound Lightning invoice

Improvements You Can Make

You can add LNURL-pay functionality which will allow the bank users to have a static payment URL, they will provide a minSendable and maxSendable. When a Lightning wallet that process LNURL-payment scans the QRcode it will prompt the wallet user to pay an amount within the min and max amount specified by the LNURL-pay creator.

BOLT 11 invoices are unsafe to use because after successful payment the payment secret (preimage) is revealed and known by all the participants in the payment route.

If another payment is made using the same invoice hash, any node along the payment route can settle the payment and gain the entire payment amount rather than forward the HTLC to collect a routing fee if the payment is completed. For this reason, it is unsafe to use a payment request more than once


Lightning is a super cool technology that makes Bitcoin payments very fast, one can send sats to a Lightning user located on a different continent in milliseconds, Lightning payments are as fast as the sender's internet speed.

There are a couple of ways a user can start using this amazing technology:

  • They can use a custodial Lightning wallet e.g wallet of satoshi
  • If they want more control, they can choose a platform that supports hosted Lightning channels
  • A user will have total control if they decide to setup up their Lightning node, and create their own payment channels

If you are an African developer and you are interested in transitioning into Bitcoin development, the Qala program is perfect for you, consider registering for the next Qala cohort.

Thank you.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store