Skip to content

Developing with LNbits

arbadacarba edited this page Oct 7, 2023 · 19 revisions

General help on the LNURL-specification and a list of services, libraries and development tools can be found here in a repo of fiatjaf.

The Open Swagger API docs page shows how LNbits adresses these as well as these hints on using it and also these readymade function example on paying a lnaddress or invoice from Judy. For this you might need the Lightning Decoder to decode the lnaddress to a LNURL.

As a start, here´s an example how to crawl with a python script for all comments that have been received to payments, that Hannes made

import requests
import json
from requests.structures import CaseInsensitiveDict

# API Call
LNBITS_URL = "https://legend.lnbits.com"
LNBITS_APIKEY = "cd6c5702242e42de818055f5c9602556"

url = LNBITS_URL + "/api/v1/payments/"
headers = CaseInsensitiveDict()
headers["Content-Type"] = "application/json"
headers["X-Api-Key"] = LNBITS_APIKEY    

content = json.loads(requests.get(url, headers=headers).content)
for x in content:
    if ("tag" in x["extra"]) and (x["extra"]["tag"] == "lnurlp"):
    print("Payment with comment: %s and amount: %s msats" % (x["extra"]["comment"][0], x["amount"]))

Bitkarrot made a pylib with examples for the most common api reuests.

You can also find a webhook-library / examples here which are similar to the api-calls.

As a funding source for tests you can use the void (fake) wallet.

proxy-image

If you need help you can contact the LNbits dev team via the LNbits Telegram group.


Testing

For testing webhooksthis page is really handy.

For general development the LNbits project offers unit tests, that help prevent regressions. Before you can run the tests, you have to install a few dependencies:

bash
poetry install
npm i

Then to run the tests:

bash
make test

Run formatting:

bash
make format

Precommit hooks

This ensures that all commits adhere to the formatting and linting rules.

make install-pre-commit-hook

Run mypy checks:

bash
poetry run mypy

Run everything:

bash
make all

Your own extension

Anyone can create an extension by following the example extension and making extensions dev guide.

Start off by copying the extensions example into your own repo or find an extension that is similar to your approach and you want to change. We will explain the process starting off from the example but rather want to encourage you to take an existing one. Before you start also check this guide in textform or this video from Ben.

Within the manifest you can also define correlations of those extensions with the parameter "dependencies".

Each extension has a unique ID. It should be the same as the name of the extension dir and the name that you see in the URL when you are using the extension e.g. http://127.0.0.1:5000/lnurlp/?usr=a2f52f9b396249c7a561f8917a5b2dbd where the ID is "lnurlp". It is recommended for the ID to be alphaumeric only (no -, _, . etc). The repo name is recommended to be the same as the extension ID for a better overview, but it is not mandatory.

You dont need a zip or filehash if you dont want to deploy it to official LNbits extentensions.json repo. If you do want to add it to LNbits you will need to create a release and hash it. If its not ment to get released with LNbits you can just update the hash property in your own extension.json.

Please also include the api-request parameters at least in your readme, especially for those, that will not be included into the LNbits repo.

... This document is a work-in-progress. Send pull requests if you get stuck, so others don't.

Adding new dependencies

DO NOT ADD NEW DEPENDENCIES. Try to use the dependencies that are availabe in pyproject.toml. Getting the LNbits project to accept a new dependency is time consuming and uncertain, and may result in your extension NOT being made available to others.

If for some reason your extensions must have a new python package to work, and its nees are not met in pyproject.toml, you can add a new package using venv, or poerty.


Websockets

websockets are a great way to add a two way instant data channel between server and client.

LNbits has a useful in built websocket tool. With a websocket client connect to (obv change somespecificid) wss://legend.lnbits.com/api/v1/ws/somespecificid (you can use an online websocket tester). Now make a get to https://legend.lnbits.com/api/v1/ws/somespecificid/somedata.

You can send data to that websocket by using from lnbits.core.services import websocketUpdater and the function websocketUpdater("somespecificid", "somdata").

Example vue-js function for listening to the websocket:

initWs: async function () {
    if (location.protocol !== 'http:') {
        localUrl =
          'wss://' +
          document.domain +
          ':' +
          location.port +
          '/api/v1/ws/' +
          self.item.id
      } else {
        localUrl =
          'ws://' +
          document.domain +
          ':' +
          location.port +
          '/api/v1/ws/' +
          self.item.id
      }
    this.ws = new WebSocket(localUrl)
    this.ws.addEventListener('message', async ({data}) => {
      const res = JSON.parse(data.toString())
      console.log(res)
    })
},
register_killswitch() and unregister_killswitch(): These functions are responsible for starting and stopping a background task called killswitch_task(). The task periodically checks the LNbits status manifest for a killswitch signal and switches to the VoidWallet if the killswitch is triggered.

register_watchdog() and unregister_watchdog(): These functions are responsible for starting and stopping a background task called watchdog_task(). The task monitors the LNbits balance and node balance and switches to the VoidWallet if a specific balance delta is reached.

register_task_listeners(): This function registers an invoice listener queue for core tasks. Incoming payments in this queue trigger signals sent to other extensions and fulfill other core tasks, such as dispatching webhooks.

wait_for_paid_invoices(): This function is an infinite loop that waits for paid invoices in the invoice_paid_queue. It dispatches events to all extensions, sends webhooks, and handles balance notifications.

dispatch_api_invoice_listeners(): This function emits events to invoice listeners subscribed from the API. It sends invoice paid events to the specified channels.

dispatch_webhook(): This function dispatches a webhook to the specified webhook URL using the httpx library. It sends a POST request with payment data as JSON and marks the webhook status based on the response.

mark_webhook_sent(): This function updates the webhook status of a payment in the database.