When you think of LNURL the first thing that may come into your mind might be an internet identifier, like email@example.com, or a static QR Code that can be used to pay someone over the Lightning Network. It turns out that LNURL is much more than that. In this article, we’ll understand what LNURL is, how it works, and the multiple things that can be done.
Basics of LNURL
LNURL is a protocol built on top of HTTP, the standard communication protocol on the internet, that enables Lightning clients to communicate, coordinate and execute a wide variety of tasks in the lightning network. The protocol is an open-source project available on GitHub. As of this date, it contains 20 documents, each called a “LUD” (LnUrl Document) that describe different pieces of the protocol that wallets and service providers can implement.
In this article, we’ll cover the most known LUDs, but before going into details, let’s go through what every LNURL task has in common. The flow is typically the same: it starts with someone, usually using an LN wallet, scanning a QR Code that represents an LNURL. The LNURL is a long string of characters, encoded with bech32, the same encoding scheme used for SegWit Addresses. This string, when decoded, is a regular internet URL.
Subsequently, the LN wallet initiates a request to the decoded URL. The server that receives this request issues a reply message containing pertinent information and instructions on how to proceed, which varies depending on the action’s nature.
With the information and instructions in hand, the LN wallet might perform some actions on the Lightning Network and keep communicating with the server as needed. The server might also perform actions on the Lightning Network if needed.
LNURL is a very general protocol. This approach of exchanging information and instructions that are then executed in the Lightning Network gives developers a sandbox where they can create a wide variety of features that enhance Lightning Network’s user experience. In its essence, LNURL is a protocol that facilitates coordination between Lightning clients and removes some of the complexity for the end user. Let’s see some concrete examples by exploring some of the different capabilities of LNURL.
LNURL Channel Requests
The early days of the Lightning Network were reserved for those with the knowledge and curiosity to tinker around with experimental software, mainly the “shadowy super-coders” that were already involved with Bitcoin development. But even though these people were used to the complexity of Bitcoin and Lightning, there was a lot of friction to use the network.
Notably, one of the struggles was actually being able to receive payments. That’s because to receive a payment in the Lightning Network, you must have a payment channel with inbound liquidity – that is, bitcoin that it’s on the “remote” side of the channel and can move in your direction. In those earlier days, when only Single Funded Channels were available, the person that initiated the request to open the channel would have all funds in the local side of the payment channel.
When you initiate the open channel request, liquidity starts on your side.
This meant that, in order to receive payments over the Lightning Network, you would need that someone requested to open a channel with you, locking the coins on the remote node. That way satoshis could be pushed to your side of the channel, enabling you to receive a payment.
When your peer initiates the open channel request, liquidity starts on their side.
This was before solutions like Magma, Pool, and Liquidity Ads came around. Imagine having to find someone willing to open a channel with you just to be able to receive a payment. Definitely not the best user experience.
LNURL first came to address this issue. The original idea was to pay someone to open a channel with you. So developers from Simple Bitcoin Wallet and Bitrefill designed what turned out to be LNURL’s first specification, the `channelRequest`. A channel request enables the end user to acquire inbound liquidity by buying it from a service provider. It works like this:
A service provider would offer you an invoice, and after paying it would display a QR Code. The user scans the QR Code, decodes it, and sends a request to the decoded URL. Then the server responds with some data that contains:
- The remote node address;
- A second URL, called “callback”, that when accessed by the client indicates to the service provider that it wishes to continue with the process;
- A sequence of characters, to be used with the callback, that identifies the user’s wallet, called “k1”;
- A tag, which is an identifier for the type of LNURL action taking place, in this case, a `channelRequest`.
Then the wallet uses the remote node address to connect with it over the Lightning Network. Rember, connecting is not the same as opening a channel, a connection is simply a requirement for opening a channel. With both nodes connected, the wallet sends a request using the “callback” URL, providing k1, the local node ID, and a flag to inform the other party if this should be an announced channel or not. Finally, the service provider opens the channel with the user.
This facilitates the process of acquiring inbound liquidity. There was no need anymore to go out trying to find people willing to open a channel to you. With channel requests, you could simply pay and wait for the inbound liquidity.
LNURL Withdraw Request
Another issue with the Lightning Network in its current form is the impossibility to make “offers”. This creates awkward and unintuitive user experiences. In a Bitcoin ATM, for instance, if you want to insert your local currency bills and get paid over lightning either you’ll have to type your invoice manually or the ATM needs to have a camera to read the QR code for the invoice you create. It would be much better if you could scan a QR code from the ATM screen and have the ATM pay you.
LNURL Withdraw Requests fixes this! This protocol enables a lightning node to create a static QR code that can be used to withdraw funds when someone interacts with it. If the Bitcoin ATM supported LNURL Withdraw requests, it would display a QR Code that a person can scan with a wallet that also supports LNURL Withdraw. The wallet then makes a request to the URL and the server responds with information and instructions on how to proceed. In particular, the server response contains:
- A minimum withdrawal amount;
- A maximum withdrawal amount;
- A description to use in the invoice;
- The callback URL that is going to be used in the next request the LN Wallet makes.
- The “k1” identifier that the LN wallet must send along with the callback to identify the wallet.
- The tag, which identifies the type of LNURL, in this case, a “Withdraw Request”;
Upon receiving the request, the wallet lets the user select an amount to receive, which is bound by the minimum and maximum amounts in the server’s response. The wallet then sends an invoice for the desired amount along with the k1 identifier to the callback URL. With the invoice in hand, the server can use its lightning node to pay the invoice and complete the withdrawal request.
If you ever heard of BOLT 12 “offers” you might know that it addresses the exact same issue. The main difference between BOLT 12 “offers” and LNURL Withdraw is that the first wants to solve the issue using only the Lightning Network, without the need to use a server to handle the coordination between peers. While it’s true that BOLT 12 is better in terms of privacy and sovereignty it’s worth noting that BOLT 12 specification is still under development so it has limited support at the moment.
LNURL Pay Request
Imagine you decide to share your insane Pac-Man skills with others by streaming your gameplay on a streaming service. You also want to be able to receive tips in bitcoin for the great quality content you’re going to provide. You can’t use on-chain Bitcoin because mining fees can get expensive for small tips, so you decide to use the Lightning Network.
But there is a problem: every lightning payment requires a new invoice. This means that you can’t just display the QR Code for an invoice in your stream, you need to generate a new invoice for every person that wants to tip you, and instead of viewers just paying you, they need to ask you to create an invoice for their tip. Then you need to stop your gameplay, create an invoice, and share it exclusively with the person that wants to tip you. Do I need to say what would happen with your viewership if you constantly stopped your gameplay to create invoices? There’s no way Bitcoin can compete in the tips for streamers market if it can’t provide a better user experience.
Here’s where LNURL Pay Requests are useful. This protocol enables the use of static QR codes for payments and it looks very similar to LNURL Withdraw Requests but now the person that scans the QR code will send the money instead of receiving it. This should be easy by now: the user scans a QR code and makes a request to the decoded URL, and the server responds with:
- A minimum amount that the service is willing to receive;
- A maximum amount that the service is willing to receive;
- A metadata field, that is required to pass signature verification at a later step;
- The callback URL;
- The tag, `payRequest`, in this case;
The LN wallet then lets the user select the amount to be sent, bounded by the minimum and maximum amounts provided in the response. After that, the wallet uses the callback URL to inform the service provider the selected amount. Upon receiving the second request, the server creates an invoice for the selected amount and sends it back to the wallet, finally the wallet can pay the invoice.
With this scheme, people can use static QR codes for tipping services or more elaborated use cases. Curiously, LNURL Pay Requests were developed by FiatJaf, the same person that designed the NOSTR protocol.
Paying to static internet identifiers
With LNURL Pay, developers went a step further and proposed a method of paying to an email-like address, like firstname.lastname@example.org. Instead of making a request for an URL encoded in an invoice, the wallet makes a request to voltage.com/.well-known/lnrulp/satoshi. The server then responds with the same information and instructions defined in LNURL Pay request spec and the flow continues as this was just a regular LNURL Pay request. In essence, the only thing that changed is the initial URL.
Unlike what we’ve seen so far, this one was not designed to enhance Lightning’s user experience. Instead, LNURL Auth is a protocol used for user authentication via digital signatures. A digital signature requires a public-private key pair. In essence, a Bitcoin wallet is like a keychain that holds multiple public-private key pairs. LNURL Auth takes advantage of this and uses the seed of a bitcoin wallet to generate secret authentication keys. The cool thing about this is that users are only identified by their public keys. There’s no need to use email, passwords, or usernames.
When accessing a website that has support for LNURL Auth, a user that clicks the login button will be presented with a QR Code. With a wallet that supports LNURL Auth, the user can scan the QR code and make a request to the decoded URL, and the server responds with:
- The type of action (register, login, link, auth);
- The k1 parameter, which in this case is 32 bytes of randomly generated data that will be signed by “linking private key”, a special private key generated from the seed of the bitcoin wallet.
- The tag, which in this case is `login`.
The wallet will then prompt the user to authorize the login.
After the user authorizes the login, the wallet will use the linking private key to sign k1 and sends back the signature in a subsequent request for the server. The server validates the signature against the linking public key and if the signature is valid and if so it authenticates the user.
LNURL Hosted Channel Request
A hosted channel refers to a channel that is not registered on the blockchain and whose funds are not safeguarded by the blockchain. Instead, a third party is responsible for holding the funds in custody.
This LNURL is very similar to the Channel Request LNURL. In this case, the server responds with:
- The remote node address;
- The “k1”, which in this case is a second-level secret to be used by the wallet subsequently;
- An optional alias for the node;
- The tag, which in this case is “hostedChannelRequest”;
The wallet uses the remote node address to connect with it and once connected, it sends an `InvokeHostedChannel` message to the target node using k1. The rest is handled by the Hosted Channel protocol being used.
LNURL in the wild
As became evident in this article, LNURL highly enhances the user experience of the Lightning Network. A lot of wallets and service providers implement different parts of the protocol, and it’s very easy to find bitcoiners on Twitter with their “LN Address” on their bio. One of the coolest features of LNURL is that it can be used to replicate the experience that a user would have with regular finance applications and this facilitates onboarding people into Bitcoin.
See for example Praia’s Bitcoin “Fruits for 10 sats” project, where LNURL Pay is used to replicate the user experience of paying for something with a debit/credit card.
As you can see, it’s so simple that even kids can do it. No need to understand Lightning’s intricacies, simply tap and forget.
Perhaps one of the most popular use cases for LNURL right now is NOSTR “Zaps”, a feature that enables NOSTR users to send satoshis to each other from their NOSTR client.
This enables NOSTR users to get paid for content people deem valuable, which at the moment seems to be mostly memes.
Despite its popularity, LNURL has also a lot of critiques that argue that LNURL incentives the use of custodial services because it requires an internet server to support the protocol, and that goes against Bitcoin’s ethos to be money without trusted parties. That’s a valid critique, but it’s also important to say that plenty of options are available that help people to use LNURL with sovereignty, with LNBits being one of the most popular options.
The reality is that Lightning is still far from achieving the same experience enabled by LNURL and may never get there. The best that can be done right now is to educate people on the tradeoffs of using LNURL with third-party servers and incentive developers to design native solutions on Lightning. BOLT 12, for instance, can be used to generate static QR Codes for payments and “offers”. This alternative is more private than LNURL’s solution, but the specification is yet to be ratified, meaning the protocol can still change. Here at Voltage, we want users to hold their keys. This is why we recently released the NOSTR Toolkit, tool that enables you to receive zaps directly to your node, without the need for custodial solutions. If you want to know how you can keep your sovereignty using NOSTR you can follow our tutorial.
Begin building on Voltage Today!