clean
This commit is contained in:
@@ -70,10 +70,6 @@ FORWARDED_ALLOW_IPS="*"
|
|||||||
# Inside this directory the `extensions` and `upgrades` sub-directories will be created.
|
# Inside this directory the `extensions` and `upgrades` sub-directories will be created.
|
||||||
# LNBITS_EXTENSIONS_PATH="/path/to/some/dir"
|
# LNBITS_EXTENSIONS_PATH="/path/to/some/dir"
|
||||||
|
|
||||||
# === WASM Extensions Sandbox Limits ===
|
|
||||||
# LNBITS_WASM_TIMEOUT_SECONDS=3.0
|
|
||||||
# LNBITS_WASM_MAX_MODULE_BYTES=1000000
|
|
||||||
# LNBITS_WASM_MAX_DB_OPS_PER_MIN=120
|
|
||||||
|
|
||||||
# ID of the super user. The user ID must exist.
|
# ID of the super user. The user ID must exist.
|
||||||
# SUPER_USER=""
|
# SUPER_USER=""
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
---
|
|
||||||
layout: default
|
|
||||||
parent: For developers
|
|
||||||
title: Agent Guide - Python Extensions
|
|
||||||
nav_order: 4
|
|
||||||
---
|
|
||||||
|
|
||||||
# Agent Guide - Python Extensions
|
|
||||||
|
|
||||||
This guide is for AI agents or developers using AI to build **traditional (Python) LNbits extensions**. It defines what to change, what not to change, and the expected structure.
|
|
||||||
|
|
||||||
## Hard Rules (Non-Negotiable)
|
|
||||||
|
|
||||||
- Do **not** change core LNbits files.
|
|
||||||
- Only edit files inside your extension folder.
|
|
||||||
- Do **not** add new Python dependencies unless explicitly approved.
|
|
||||||
|
|
||||||
## Extension Folder Layout (Python)
|
|
||||||
|
|
||||||
Your extension lives under:
|
|
||||||
|
|
||||||
```
|
|
||||||
lnbits/extensions/<ext_id>/
|
|
||||||
```
|
|
||||||
|
|
||||||
Typical files to edit:
|
|
||||||
|
|
||||||
- `views.py` (HTML routes)
|
|
||||||
- `views_api.py` (API routes)
|
|
||||||
- `crud.py` / `models.py` (storage logic + models)
|
|
||||||
- `migrations.py` (DB schema)
|
|
||||||
- `templates/<ext_id>/` (HTML)
|
|
||||||
- `static/` (JS/CSS/images)
|
|
||||||
- `config.json`, `manifest.json`, `README.md`
|
|
||||||
|
|
||||||
## What You Can Do
|
|
||||||
|
|
||||||
Python extensions can:
|
|
||||||
|
|
||||||
- Define their own database schema via `migrations.py`
|
|
||||||
- Run long-running background tasks via `*_start()` and `*_stop()` hooks
|
|
||||||
- Access LNbits internal services directly in Python
|
|
||||||
- Expose custom API routes under `/<ext_id>/api/v1/...`
|
|
||||||
|
|
||||||
## What You Must Not Do
|
|
||||||
|
|
||||||
- Do not modify core services or routes.
|
|
||||||
- Do not patch LNbits internals for your extension.
|
|
||||||
- Avoid direct DB access outside your own schema.
|
|
||||||
|
|
||||||
## Background Tasks
|
|
||||||
|
|
||||||
Implement background tasks by exposing:
|
|
||||||
|
|
||||||
```
|
|
||||||
def <ext_id>_start():
|
|
||||||
def <ext_id>_stop():
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `register_invoice_listener` or `wait_for_paid_invoices` if you need to react to payments.
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
- Extension loads without errors.
|
|
||||||
- Migrations apply cleanly.
|
|
||||||
- Routes are registered under `/<ext_id>/...`.
|
|
||||||
- Background tasks start/stop cleanly.
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
---
|
|
||||||
layout: default
|
|
||||||
parent: For developers
|
|
||||||
title: Agent Guide - WASM Extensions
|
|
||||||
nav_order: 3
|
|
||||||
---
|
|
||||||
|
|
||||||
# Agent Guide - WASM Extensions
|
|
||||||
|
|
||||||
This guide is written for AI agents or developers using AI to build LNbits WASM extensions. It describes what to change, what not to change, and the available capabilities/limits.
|
|
||||||
|
|
||||||
## Hard Rules (Non-Negotiable)
|
|
||||||
|
|
||||||
- Do **not** change core LNbits files. Only edit files inside your extension folder.
|
|
||||||
- Do **not** add new Python dependencies.
|
|
||||||
- Do **not** rely on long-running WASM processes. WASM runs per-call with timeouts.
|
|
||||||
|
|
||||||
## Extension Folder Layout (WASM)
|
|
||||||
|
|
||||||
Your extension lives under:
|
|
||||||
|
|
||||||
```
|
|
||||||
lnbits/extensions/<ext_id>/
|
|
||||||
```
|
|
||||||
|
|
||||||
You should only edit files under this folder, typically:
|
|
||||||
|
|
||||||
- `config.json` (metadata, permissions, tags, public handlers)
|
|
||||||
- `wasm/` (your `module.wasm` or `module.wat`)
|
|
||||||
- `static/` (frontend assets)
|
|
||||||
- `templates/` (HTML pages)
|
|
||||||
- `manifest.json`, `README.md`, `description.md` (docs and metadata)
|
|
||||||
|
|
||||||
## Required Config Fields
|
|
||||||
|
|
||||||
In `config.json`:
|
|
||||||
|
|
||||||
- `id` / `name`
|
|
||||||
- `extension_type: "wasm"`
|
|
||||||
- `permissions` (required API permissions)
|
|
||||||
- `public_wasm_functions` (handlers callable from public routes)
|
|
||||||
- `public_kv_keys` (publicly readable KV keys)
|
|
||||||
- `payment_tags` (list of tags the user may grant for watcher access)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": "myext",
|
|
||||||
"name": "MyExt",
|
|
||||||
"extension_type": "wasm",
|
|
||||||
"permissions": [
|
|
||||||
{"id": "ext.db.read_write", "label": "DB access", "description": "..."},
|
|
||||||
{
|
|
||||||
"id": "api.POST:/api/v1/payments",
|
|
||||||
"label": "Create invoices",
|
|
||||||
"description": "..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ext.payments.watch",
|
|
||||||
"label": "Watch payments",
|
|
||||||
"description": "..."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ext.tasks.schedule",
|
|
||||||
"label": "Schedule tasks",
|
|
||||||
"description": "..."
|
|
||||||
},
|
|
||||||
{"id": "ext.db.sql", "label": "SQL access", "description": "..."}
|
|
||||||
],
|
|
||||||
"public_wasm_functions": [
|
|
||||||
"public_create_invoice",
|
|
||||||
"on_tag_payment",
|
|
||||||
"on_schedule"
|
|
||||||
],
|
|
||||||
"public_kv_keys": ["public_lists", "public_tasks"],
|
|
||||||
"payment_tags": ["coinflip", "myext"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## What the WASM Host Can Do
|
|
||||||
|
|
||||||
WASM runs in a short-lived subprocess. It can:
|
|
||||||
|
|
||||||
- Read/write extension KV (`/api/v1/kv/*`)
|
|
||||||
- Read/write secret KV (`/api/v1/secret/*`)
|
|
||||||
- Call internal LNbits endpoints (only if declared + granted)
|
|
||||||
- Publish websockets (`ws_publish`)
|
|
||||||
- Run backend tag watchers and scheduled handlers (server-side triggers)
|
|
||||||
|
|
||||||
## Permissions Model
|
|
||||||
|
|
||||||
Your extension can only call or access what is declared and granted:
|
|
||||||
|
|
||||||
- `api.METHOD:/path` for internal endpoints (core or other extensions)
|
|
||||||
- `ext.db.read_write` for KV access
|
|
||||||
- `ext.payments.watch` for payment watchers
|
|
||||||
- `ext.tasks.schedule` for scheduled jobs
|
|
||||||
- `ext.db.sql` for SQL interface
|
|
||||||
|
|
||||||
If the endpoint doesn’t exist, permissions won’t save.
|
|
||||||
|
|
||||||
## Tag Watchers (Backend)
|
|
||||||
|
|
||||||
You can register tag watchers:
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /<ext_id>/api/v1/watch_tag
|
|
||||||
{
|
|
||||||
"tag": "coinflip",
|
|
||||||
"wallet_id": "<wallet-id>",
|
|
||||||
"handler": "on_tag_payment",
|
|
||||||
"store_key": "tag:coinflip:last_payment"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Constraints:
|
|
||||||
|
|
||||||
- Tag must be in `payment_tags` and granted by the user.
|
|
||||||
- Watchers are persisted and restored on restart.
|
|
||||||
|
|
||||||
## Scheduled Tasks (Backend)
|
|
||||||
|
|
||||||
You can schedule periodic handlers:
|
|
||||||
|
|
||||||
```
|
|
||||||
POST /<ext_id>/api/v1/schedule
|
|
||||||
{
|
|
||||||
"interval_seconds": 30,
|
|
||||||
"handler": "on_schedule",
|
|
||||||
"store_key": "schedule:last_run"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Constraints:
|
|
||||||
|
|
||||||
- Requires `ext.tasks.schedule` permission.
|
|
||||||
- Minimum interval is 5 seconds.
|
|
||||||
- Stored in extension KV and restored on restart.
|
|
||||||
|
|
||||||
## SQL Interface (Limited)
|
|
||||||
|
|
||||||
You can run SQL within your extension schema:
|
|
||||||
|
|
||||||
- `/api/v1/sql/query` (SELECT only)
|
|
||||||
- `/api/v1/sql/exec` (limited DDL/DML)
|
|
||||||
|
|
||||||
Rules:
|
|
||||||
|
|
||||||
- Single statement only
|
|
||||||
- No `PRAGMA`, no `sqlite_master`
|
|
||||||
- No cross-schema access
|
|
||||||
|
|
||||||
## Public Pages (No Keys)
|
|
||||||
|
|
||||||
Public pages must not depend on `window.g` or wallet keys.
|
|
||||||
They can call:
|
|
||||||
|
|
||||||
- `/{ext_id}/api/v1/public/kv/{key}`
|
|
||||||
- `/{ext_id}/api/v1/public/call/{handler}`
|
|
||||||
|
|
||||||
## What Not To Do
|
|
||||||
|
|
||||||
- Do not write to core routes or override existing LNbits paths.
|
|
||||||
- Do not add background threads; use watchers or scheduler instead.
|
|
||||||
- Do not assume the WASM process persists.
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
- Permissions show correctly in the extensions UI.
|
|
||||||
- Public handlers are in `public_wasm_functions`.
|
|
||||||
- Public KV keys are explicitly listed.
|
|
||||||
- Tag watchers only use allowed tags.
|
|
||||||
- Scheduled handlers run and update KV as expected.
|
|
||||||
@@ -1 +1 @@
|
|||||||
from lnbits.extensions.wasm.wasm_host import * # noqa: F403
|
from lnbits.extensions.wasm.wasm_host import * # noqa: F401,F403
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from lnbits.extensions.wasm.wasm_host.extension_host import * # noqa: F403
|
from lnbits.extensions.wasm.wasm_host.extension_host import * # noqa: F401,F403
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from lnbits.extensions.wasm.wasm_host.runner import * # noqa: F403
|
from lnbits.extensions.wasm.wasm_host.runner import * # noqa: F401,F403
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from lnbits.extensions.wasm.wasm_host.service import * # noqa: F403
|
from lnbits.extensions.wasm.wasm_host.service import * # noqa: F401,F403
|
||||||
|
|||||||
@@ -75,9 +75,6 @@ class ExtensionsSettings(LNbitsSettings):
|
|||||||
lnbits_extensions_builder_manifest_url: str = Field(
|
lnbits_extensions_builder_manifest_url: str = Field(
|
||||||
default="https://raw.githubusercontent.com/lnbits/extension_builder_stub/refs/heads/main/manifest.json"
|
default="https://raw.githubusercontent.com/lnbits/extension_builder_stub/refs/heads/main/manifest.json"
|
||||||
)
|
)
|
||||||
lnbits_wasm_timeout_seconds: float = Field(default=3.0, ge=0.1)
|
|
||||||
lnbits_wasm_max_module_bytes: int = Field(default=1_000_000, ge=0)
|
|
||||||
lnbits_wasm_max_db_ops_per_min: int = Field(default=120, ge=0)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extension_builder_working_dir_path(self) -> Path:
|
def extension_builder_working_dir_path(self) -> Path:
|
||||||
|
|||||||
Reference in New Issue
Block a user