-
Notifications
You must be signed in to change notification settings - Fork 0
Development
-
clink/— extension package (see Architecture) -
tests/— pytest suite -
.github/workflows/release.yml— tag-triggered release pipeline -
tools/update_extensions.py— registry updater for the LNbits extension market
The repo basename lnbits-clink is not a valid Python identifier, and LNbits loads the extension from its extensions/clink folder. tests/run_tests.sh reproduces that by symlinking the repo into a temp dir named clink:
# with lnbits installed in the active environment
tests/run_tests.sh
# or pointing at a specific interpreter
PYTEST_PYTHON=/path/to/venv/bin/python tests/run_tests.sh
# run one file
tests/run_tests.sh -q clink/tests/test_subscriptions.pyThe suite covers the protocol layer (NIP-44 vectors, bech32 codecs, event sign/verify), the node service, Pay Offers, and the subscriptions engine. It also contains tests/vectors/nip44.vectors.json, a curated NIP-44 test vector set.
python -m ruff check .
python -m black --check .- Target: Python
>= 3.10, line length 88. -
nostr/andtests/vectors/are excluded from mypy; ruff/black run over the whole tree.
On LNbits 1.5.x windowMixin is empty ({}) and the g object (user,
wallets, settings) is injected into the core Vue app through a global
mixin (static/js/init-app.js). Extension pages create their own app
(window.app = Vue.createApp({...})), so they never receive that mixin and
this.g is undefined — reading this.g.user throws and the page renders
blank. Page components must therefore read window.g directly: a plain global
set in globals.js and populated with the logged-in user by
templates/base.html.
data() {
return {
wallets: window.g.user.wallets,
wallet: window.g.user.wallets[0]
}
}checkout.js is a public page and does not touch g.
Extension pages are in-DOM templates: templates/base.html renders the
{% block page %} markup straight into <div id="vue">, the browser parses it
as HTML, and Vue only then compiles #vue's innerHTML. The HTML parser does
not support self-closing syntax for non-void elements, so a tag like
<q-tab name="debits" ... /> is treated as an unclosed open tag that
swallows everything that follows it until a matching close tag appears. That is
exactly what happened before v0.1.2: the three q-tab elements rendered
nested inside each other (tabs stacked diagonally and overlapping), dialog
inputs overlapped, and the pay page collapsed to its header.
Rule: every component tag must use explicit closing tags — <q-tab ...></q-tab>,
<q-btn ...></q-btn>, <q-space></q-space>. Only real HTML void elements
(<img>, <br>, <input>) may be self-closing. After editing a template,
verify with:
grep -rnE '<(q-[a-z0-9-]+|qrcode-vue)\s*/>' templates/clink/ # must be empty.github/workflows/release.yml is triggered by a version tag (e.g. v0.1.2):
- Builds a release artifact (the extension zip) and drafts a GitHub release.
- Runs
tools/update_extensions.py, which updates the registry and opens a pull request againstlnbits/lnbits-extensionsso the extension shows up in the LNbits extension manager.
To cut a release:
git tag v0.1.2
git push origin v0.1.2Each tag creates a fresh branch + PR (
update-lnbits-clink-v<tag>). Close the previous PR when a newer version supersedes it.
The auto-PR needs an
EXT_GITHUBsecret (a token with access to thelnbits/lnbits-extensionsfork) configured in the repository settings.
- Commit messages follow
feat: …/fix: …style (seegit log). - All commits are authored under a dedicated extension identity (
WoompaLoompa/06bc1a977d@atomicmail.io). - No new Python dependencies: protocol primitives are implemented in
clink/nostron top of LNbits' bundled packages.
lnbits-clink — CLINK (Nostr-native Lightning) for LNbits.