Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/arcbtc/LNURLPoS
Offline lightning PoS
https://github.com/arcbtc/LNURLPoS
Last synced: about 2 months ago
JSON representation
Offline lightning PoS
- Host: GitHub
- URL: https://github.com/arcbtc/LNURLPoS
- Owner: arcbtc
- License: gpl-3.0
- Created: 2021-09-13T23:03:49.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2023-10-05T12:33:04.000Z (over 1 year ago)
- Last Synced: 2024-08-02T20:44:37.842Z (5 months ago)
- Language: C
- Size: 4.43 MB
- Stars: 204
- Watchers: 11
- Forks: 34
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-citadel - LNURLPoS - cheap, offline, hardware device that accepts Lightning payments (Finance / Hardware)
README
# LNURLPoS
## Cheap, offline(!), DIY bitcoin lightning-network PoS
### for a more up to date version of lnurlpos, checkout bitcoinPoS
![lnurlpos](https://user-images.githubusercontent.com/33088785/134943216-1a9f3ab6-09da-4e15-b16a-2c2f8bc918da.png)
Lightning-network uses hot wallets and real-world payments are made from phones. The burden of connectivity can be taken away from the point-of-sale and given to the phone.
![image](https://user-images.githubusercontent.com/33088785/134652952-cf5c95ac-afc2-4175-8d09-a983c3f066bc.png)
> Join our telegram support/chat.
> For a traditional PoS experience see my LNPoS project.
> The manufacturer of the microcontroller used have actually released a specific kit for LNURLPoS! LiLyGos repo.
LNURLPoS uses the LNURL-pay protocol. LNURL-pay allows your lightning-wallet to make a secure request to a server to get a lightning-network invoice. So instead of scanning a massive ugly lightning-network invoice QR, you can scan a lovely little LNURL QR (if you decode an LNURL you'll see its just a URL).
![image](https://user-images.githubusercontent.com/33088785/134657379-bd9e18f0-0289-498b-a1fc-c084c60e64e3.png)
For online stuff I suppose massive QR codes are not an issue, but when fiddling with hardware devices they are. LNURLPoS using the LNURL-pay protocol, it can use a smaller screen for displaying the QR.
### Setup workflow
- LNURLPoS server set up and register PoS in a few clicks on LNbits using the LNURLPoS extension
- Copy credentials (including a secret key) from server to the physical LNURLPoS device### Payment workflow
- Merchant enters amount into LNURLPoS device
- LNURL is generated in device and displayed for scanning (LNURL includes a unique pin encrypted using the secret key shared with the server)
- Customer scans and pays
- When the payment has cleared the customer is sent the decrypted unique pin
- Merchant can compare and verify using the same pin displayed on the lNURLPoS### Credit/props
Stepan Snigerev for creating beautiful crypto and LNURL encoding functions.
Fiatjafs incredible OfflineShop extension. LNURLPoS is the same concept, but can run at scale, and is dependent on a device.
Belskomat for pironeering the idea of a shared secret for the microcontroller to encrypt data with.
# ⚡⚡⚡⚡⚡⚡ LNURLPoS Tutorial ⚡⚡⚡⚡⚡⚡
### Hardware needed
- Lilygo TTGO T-Display
- Keypad membrane (these big ones are easy to find, these smaller ones will be used for workshops by arcbtc).
- Angled male/male GPIO pins### Arduino software install
- Download/install latest Arduino IDE
- Install ESP32 boards, using boards manager
- Copy these libraries into your Arduino IDE library folder
- Plug in T-Display, from _Tools>Board>ESP32 Boards_ select **TTGO LoRa32 OLED V1**> _Note: If using MacOS, you will need the CP210x USB to UART Bridge VCP Drivers available here https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers_
### LNbits extension
To make things easy (usually a few clicks on things like Raspiblitz), there is an LNbits extension.
If you want to make your own stand-alone server software that would be fairly easy to do, by replicating the lnurl.py file in the extennsion.### Future updates
At the beginning of this article I said "LNURLPoS (currently) only uses LNURL-Pay". The next stage will be for the PoS to also create LNURL-Withdraws, which are essentially faucets. This means merchants can offer refunds, and also sell bitcoin over the counter, which creates an extremely powerful tool for local economies on-ramping and off-ramping from their local fiat currency.
At Adopting Bitcoin in San Salvador I will distribute 40 kits over x2 workshops, so hopefully some locals will start producing, selling and teaching others how to make these useful little units.
---
## Deeper Dive
### LNURL
Much of the innovation that happens on lightning-network uses an additional protocol layer called LNURL.
LNURL is just a bech32 encoded URL string, that is a link to an LNURL server that your lightning wallet can request information from. By your wallet being able to communicate with a server, developers are no longer bound by the _payee-generate-invoice_ workflow. There are many different types of LNURL. LNURLPoS (currently) only uses LNURL-Pay.
This is an LNURL-pay QR code:
![image](https://user-images.githubusercontent.com/33088785/136535559-7e351bac-781d-4a53-9643-fa8ebcad7aef.png)
This is the data in that QR code:
`LNURL1DP68GURN8GHJ7MRWVF5HGUEWVDHK6TMVDE6HYMRS9ASHQ6F0WCCJ7MRWW4EXCTECXVUQR8PUDZ`
If we decode the LNURL we get this URL:
`https://legend.lnbits.com/lnurlp/api/v1/lnurl/838`
If you do a GET request to the URL this data will be returned (you can test this by just visiting the URL in a browser):
```
{
"callback": "https://lnbits.com/lnurlp/api/v1/lnurl/cb/838",
"maxSendable": 10000000000,
"metadata": "[[\"text/plain\", \"Lovely little QR\"]]",
"minSendable": 10000,
"tag": "payRequest"
}
```When your wallet gets this json it asks you how much you want to send between the `minSendable` and `maxSendable`.
After a moment you get a “payment sent” confirmation and receipt.
So what happened?
When you verify you want to send say 10sats, your wallet sends that data (as a json) to the `callback` URL. The server then generates an invoice for that amount and sends it back to your wallet, which pays it. Once the payment has cleared, the wallet reveals a receipt to you.
### LNURLPoS workflow
LNURLPoS generates and encodes the LNURL in the device, which means we can pass some data in the URL.
The LNURLPoS stores four important pieces of data:
- URL to your LNURL server (we’re using an LNbits install, with dedicated extension)
- PoS ID (Unique ID generated in the LNbits extension)
- Secret (Secret shared with the LNURL server)
- Currency denomination (being offline sats becomes too volatile)LNURLPoS could use any LNURL server that performs some certain functions, but to make things easy I made an extension in LNbits specifically for LNURLPoS
![image](https://user-images.githubusercontent.com/33088785/136534237-d1ec7a3f-7937-43b0-91d7-b5cd9587389b.png)
![image](https://user-images.githubusercontent.com/33088785/136534873-92d080d5-7825-4358-8dd5-3d04009aa80b.png)Once a PoS has been generated the extension gives you this data:
```
String server = "https://lnbits.com";
String posId = "L4aJNiQZyPxCREoB3KXiiU";
String key = "4TPLxRmv82yEFjUgWKdfPh";
String currency = "EUR";
```The data can then be passed to the device when uploading its software through the Arduino IDE
When an amount is entered into the LNURLPoS, the device generates a unique pin, then encrypts the amount+pin using the shared secret and a nonce. The server endpoint, nonce, encypted data, and PoS ID are built into into the LNURL.
`https://lnbits.com/lnurlpos/api/v1/lnurl///`
`LNURL1DP68GURN8GHJ7MRWVF5HGUEWVDHK6TMVDE6HYMRSDAEJ7CTSDYHHVVF0D3H82UNV9U7XUMMWVDJNUTEUV4HXXUNEWP6X2EPDV3SHGCF79U78QMMN945KG0S2PG6GTWSK`
When that first GET request happens from the wallet, the LNURL server can find the PoS record, fetch its secret use the secret to decrypt the amount+pin. The amount is converted from the fiat currency to sats, and sent back to the wallet as `minSendable` and `maxSendable`.
If the invoice passed to the wallet is paid the customer is given access to the decrypted pin.