Compare commits

..
41 Commits
Author SHA1 Message Date
arcbtc 161eaec5bc fix: remove OpenSats
Apparently our application "wasn't compelling enough", so we are no longer supported by a grant.
Despite all those sleepless nights, working through weekends, 1.2k gh stars, +100k users, countless projects that depend on LNbits in their stack, continues innovation and R&D.
We should have made some froffy broware I suppose 🤷, rather than actual useful software/hardware.
2026-02-24 04:48:39 +00:00
dni ⚡andGitHub 2069e3de8b chore: update to v1.5.0-rc2 (#3806) 2026-02-20 10:04:59 +01:00
Vlad StanandGitHub 800be6042f fix: paypal subscriptions (#3797) 2026-02-20 10:56:08 +02:00
dni ⚡andGitHub c65d373f23 feat: restructure docker images, add sparkl2 docker image (#3794) 2026-02-18 13:52:19 +01:00
dni ⚡andGitHub 087e095bcf feat: hide first_install_token if is not required (#3795) 2026-02-18 13:52:02 +01:00
dni ⚡andGitHub 027a161494 chore: update lnbits to version v1.5.0-rc1 (#3793) 2026-02-17 12:26:50 +01:00
83ef05696e feat: Spark L2 (#3715)
Co-authored-by: blackcoffeexbt <87530449+blackcoffeexbt@users.noreply.github.com>
Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
2026-02-17 12:25:38 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
42962308e6 chore(deps): bump pillow from 12.1.0 to 12.1.1 (#3785)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-17 11:33:28 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>Vlad Stan
783ee256a1 chore(deps): bump axios from 1.13.2 to 1.13.5 (#3786)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
2026-02-17 11:32:58 +01:00
4e805fd00e feat: modern theme stuff like rounded corners and card gradient (#3766)
Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
2026-02-16 08:06:36 +01:00
dni ⚡andGitHub f54824cc44 fix: /first_install new superuser may duplicate an username (#3787) 2026-02-13 14:44:52 +00:00
ArcandGitHub 768d2cbe2a fix: fail closed on PayPal webhook verification errors (#3769) 2026-02-10 08:50:50 +01:00
krviandGitHub efd36d0221 fix: use canonical values in rate limit unit select (#3753) 2026-02-09 10:43:03 +02:00
Vlad StanandGitHub 4684939e13 fix: validation of invitation code (#3767) 2026-02-05 18:53:01 +02:00
Vlad StanandGitHub 193ee20da4 [feat] User invitation code (#3761) 2026-02-05 12:35:24 +02:00
Vlad StanandGitHub 2fe7ab4f83 [feat] Allow no exchange providers (#3763) 2026-02-05 11:11:48 +01:00
dni ⚡andGitHub 10c8ca4ca1 fix: datetime in db.py added utc offset (#3762) 2026-02-05 11:05:58 +01:00
Vlad StanandGitHub f079762b71 fix: handle validation errors when the response is binary (#3765) 2026-02-05 11:55:40 +02:00
Vlad StanandGitHub 2e042d2597 fix: extension paid/free label (#3764) 2026-02-05 11:32:46 +02:00
Vlad StanandGitHub 49b57c9f0b [feat] User activation (#3749) 2026-02-05 11:31:47 +02:00
dni ⚡andGitHub 656c6cac5b hotfix: websocket with old balance was sent. (#3759) 2026-02-03 12:23:49 +01:00
45e773b66f feat: FIRST_INSTALL_TOKEN to help services like Umbrel secure the first_install endpoint (#3751)
Co-authored-by: dni  <office@dnilabs.com>
2026-01-30 11:21:52 +01:00
f692ac6f12 refactor: payment.check_status() into check_payment_status(payment) (#3747)
Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com>
2026-01-30 11:18:17 +01:00
dni ⚡andGitHub 78202a027b fix: uiCustomisation JS Error (#3752) 2026-01-30 09:27:54 +01:00
dni ⚡andGitHub 28fa0906a6 refactor: g.settings with a PublicSettings class for mapping, for reactive WINDOW_SETTINGS (#3644) 2026-01-30 09:19:01 +01:00
Vlad StanandGitHub 91354f8be4 feat: wallet featured button (#3740) 2026-01-29 10:49:19 +02:00
Vlad StanandGitHub 5f5d45e89f [feat] persist user ui customization (#3743) 2026-01-29 10:35:05 +02:00
dni ⚡andGitHub 52bb125a25 chore: remove ecdsa in favor of coincurve (#3746) 2026-01-29 10:02:16 +02:00
dni ⚡andGitHub 2ca1ed897c CI: use uv for publishing on pypi (#3745) 2026-01-29 08:54:42 +01:00
Vlad StanandGitHub 631f4e8455 [feat] admin impersonate user (#3741) 2026-01-28 16:59:23 +01:00
Vlad StanandGitHub b22f88b264 fix: DB migration conflict (#3739) 2026-01-27 08:31:38 +02:00
dni ⚡andGitHub c08bc02930 chore: update python packages (#3707) 2026-01-26 08:54:37 +01:00
Vlad StanandGitHub e020a7c5a0 feat: allow text upload (#3738) 2026-01-26 09:43:52 +02:00
Vlad StanandGitHub d2e8914835 fix: better validation error messages (#3736) 2026-01-21 14:28:57 +02:00
dni ⚡andGitHub 5e79ca35ab chore: remove windowMixin from components and pages (#3632) 2026-01-21 11:26:45 +01:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4690d178a2 chore(deps): bump cryptography from 42.0.8 to 44.0.1 (#3735)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-21 11:02:28 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
c5825aa4c3 chore(deps): bump aiohttp from 3.12.15 to 3.13.3 (#3734)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-20 17:27:12 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
ebe0c4e3c3 chore(deps): bump urllib3 from 2.5.0 to 2.6.3 (#3733)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-20 17:26:45 +02:00
Djuri BaarsandGitHub 383bdb6312 [fix] Fix missing timezone information 2026-01-20 17:26:02 +02:00
a947686d79 [feat] Update extension builder for 1.4.1 (#3725)
Co-authored-by: dni  <office@dnilabs.com>
2026-01-20 14:47:54 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
28e9d32b44 chore(deps): bump werkzeug from 3.1.3 to 3.1.5 (#3732)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-20 14:46:06 +02:00
30 changed files with 809 additions and 841 deletions
+1 -8
View File
@@ -191,14 +191,7 @@ BOLTZ_CLIENT_MACAROON="/home/bob/.boltz/macaroons/admin.macaroon"
# HEXSTRING instead of path also possible # HEXSTRING instead of path also possible
BOLTZ_CLIENT_CERT="/home/bob/.boltz/tls.cert" BOLTZ_CLIENT_CERT="/home/bob/.boltz/tls.cert"
# SparkL2Wallet (external sidecar: https://github.com/lnbits/spark_sidecar) # TODO: add Spark
SPARK_L2_NETWORK=MAINNET
SPARK_L2_EXTERNAL_ENDPOINT=http://127.0.0.1:8765
SPARK_L2_EXTERNAL_API_KEY=
# optional tuning
# SPARK_L2_PAY_WAIT_MS=4000
# SPARK_L2_PAY_POLL_MS=500
# SPARK_L2_STREAM_KEEPALIVE_MS=15000
# StrikeWallet # StrikeWallet
STRIKE_API_ENDPOINT=https://api.strike.me/v1 STRIKE_API_ENDPOINT=https://api.strike.me/v1
+1 -1
View File
@@ -5,7 +5,7 @@
</picture> </picture>
</a> </a>
![phase: stable](https://img.shields.io/badge/phase-stable-2EA043) [![license-badge]](LICENSE) [![docs-badge]][docs] ![PRs: welcome](https://img.shields.io/badge/PRs-Welcome-yellow) [![explore: LNbits extensions](https://img.shields.io/badge/explore-LNbits%20extensions-10B981)](https://extensions.lnbits.com/) [![hardware: LNBitsShop](https://img.shields.io/badge/hardware-LNBitsShop-7C3AED)](https://shop.lnbits.com/) [<img src="https://img.shields.io/badge/community_chat-Telegram-24A1DE">](https://t.me/lnbits) [<img src="https://img.shields.io/badge/supported_by-%3E__OpenSats-f97316">](https://opensats.org) ![phase: stable](https://img.shields.io/badge/phase-stable-2EA043) [![license-badge]](LICENSE) [![docs-badge]][docs] ![PRs: welcome](https://img.shields.io/badge/PRs-Welcome-yellow) [![explore: LNbits extensions](https://img.shields.io/badge/explore-LNbits%20extensions-10B981)](https://extensions.lnbits.com/) [![hardware: LNBitsShop](https://img.shields.io/badge/hardware-LNBitsShop-7C3AED)](https://shop.lnbits.com/) [<img src="https://img.shields.io/badge/community_chat-Telegram-24A1DE">](https://t.me/lnbits)
<img width="2000" height="203" alt="lnbits_head" src="https://github.com/user-attachments/assets/77669718-ac10-43c7-ae95-6ce236c77401" /> <img width="2000" height="203" alt="lnbits_head" src="https://github.com/user-attachments/assets/77669718-ac10-43c7-ae95-6ce236c77401" />
[![tip-hero](https://img.shields.io/badge/TipJar-LNBits%20Hero-9b5cff?labelColor=6b7280&logo=lightning&logoColor=white)](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg) [![tip-hero](https://img.shields.io/badge/TipJar-LNBits%20Hero-9b5cff?labelColor=6b7280&logo=lightning&logoColor=white)](https://demo.lnbits.com/tipjar/DwaUiE4kBX6mUW6pj3X5Kg)
+2 -5
View File
@@ -26,10 +26,8 @@ password = "boltz"
host = "0.0.0.0" host = "0.0.0.0"
port = 9005 port = 9005
[swap]
deferredClaimSymbols = ["BTC", "L-BTC"]
[[pairs]] [[pairs]]
isLegacy = true
base = "BTC" base = "BTC"
quote = "BTC" quote = "BTC"
rate = 1 rate = 1
@@ -46,6 +44,7 @@ minSwapAmount = 50_000
swapTaproot = 10080 swapTaproot = 10080
[[pairs]] [[pairs]]
isLegacy = true
base = "L-BTC" base = "L-BTC"
quote = "BTC" quote = "BTC"
fee = 0.25 fee = 0.25
@@ -84,7 +83,6 @@ maxZeroConfAmount = 0
zmqpubrawblock = "tcp://bitcoind:29001" zmqpubrawblock = "tcp://bitcoind:29001"
port = 18_443 port = 18_443
cookie = "/root/.bitcoin/regtest/.cookie" cookie = "/root/.bitcoin/regtest/.cookie"
feeFloor = 0.2
wallet = "lnbits" wallet = "lnbits"
@@ -103,7 +101,6 @@ maxSwapAmount = 40_294_967
minSwapAmount = 10_000 minSwapAmount = 10_000
maxZeroConfAmount = 40_294_967 maxZeroConfAmount = 40_294_967
[liquid.chain] [liquid.chain]
host = "elementsd" host = "elementsd"
port = 18884 port = 18884
+1 -1
View File
@@ -28,7 +28,7 @@ services:
- lnd-2 - lnd-2
- boltz-postgres - boltz-postgres
restart: always restart: always
image: boltz/boltz:v3.12.1 image: boltz/boltz:latest
ports: ports:
- 9000:9000 - 9000:9000
entrypoint: "sh -c 'sleep 30; /boltz-backend/bin/boltzd'" entrypoint: "sh -c 'sleep 30; /boltz-backend/bin/boltzd'"
+2 -2
View File
@@ -50,7 +50,7 @@ Below is a side-by-side comparison of Lightning funding sources you can use with
| **Blink** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; focuses on mobile integrations. | | **Blink** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; focuses on mobile integrations. |
| **ZBD** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Gaming-focused payment platform. | | **ZBD** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Gaming-focused payment platform. |
| **Spark (CLN)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Web interface for CLN; requires Spark server setup. | | **Spark (CLN)** | Self-custodial | ❌ | Higher | ✅ | High | Manual | Moderate | High | Infrastructure cost and channel opening fees | High | Web interface for CLN; requires Spark server setup. |
| **Spark (L2)** | Self-custodial | ❌ | Medium | ❌ | High | Automatic | Easy | Low | Minimal fees | Medium | Runs via Spark sidecar; seed-based self-custody. | | **Spark (L2)** | Self-custodial | ❌ | Medium | ❌ | Medium | Automatic | Easy | Low | Minimal fees | Medium | Runs via Spark sidecar; seed-based self-custody. |
| **Cliche Wallet** | Self-custodial | ❌ | Medium | ❌ | Medium | Manual | Moderate | Moderate | Minimal fees | Medium | Lightweight wallet; suitable for embedded systems. | | **Cliche Wallet** | Self-custodial | ❌ | Medium | ❌ | Medium | Manual | Moderate | Moderate | Minimal fees | Medium | Lightweight wallet; suitable for embedded systems. |
| **Strike** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. | | **Strike** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. |
| **LNPay** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. | | **LNPay** | Custodial | ✅ | Low | ❌ | Low | Provider-managed | Easy | Low | Transaction fees apply | Medium | Third-party service; suitable for quick setups. |
@@ -60,7 +60,7 @@ Below is a side-by-side comparison of Lightning funding sources you can use with
## Spark (L2) ## Spark (L2)
Spark L2 uses a local Node.js sidecar to expose an HTTP API that LNbits can use as a funding source. It is self-custodial and secured by a standard mnemonic seed. Sidecar repo `https://github.com/lnbits/spark_sidecar`. Spark L2 uses a local Node.js sidecar to expose an HTTP API that LNbits can use as a funding source. It is self-custodial and secured by a standard mnemonic seed. You can let LNbits run the sidecar internally or run your own instance (see `https://github.com/lnbits/spark_sidecar`).
### Notes for readers ### Notes for readers
+25 -11
View File
@@ -41,8 +41,8 @@ A backend wallet is selected and configured entirely through LNbits environment
| [CoreLightning](#corelightning) | [LND (gRPC)](#lnd-grpc) | [Blink](#blink) | | [CoreLightning](#corelightning) | [LND (gRPC)](#lnd-grpc) | [Blink](#blink) |
| [CoreLightning REST](#corelightning-rest) | [LNbits](#lnbits) | [Alby](#alby) | | [CoreLightning REST](#corelightning-rest) | [LNbits](#lnbits) | [Alby](#alby) |
| [Spark (Core Lightning)](#spark-core-lightning) | [LNPay](#lnpay) | [Boltz](#boltz) | | [Spark (Core Lightning)](#spark-core-lightning) | [LNPay](#lnpay) | [Boltz](#boltz) |
| [Spark L2](#spark-l2) | [ZBD](#zbd) | [Phoenixd](#phoenixd) | | [Spark (L2)](#spark-l2) | | |
| [Cliche Wallet](#cliche-wallet) | | | | [Cliche Wallet](#cliche-wallet) | [ZBD](#zbd) | [Phoenixd](#phoenixd) |
| [Breez SDK](#breez-sdk) | [Breez Liquid SDK](#breez-liquid-sdk) | [Nostr Wallet Connect](#nostr-wallet-connect-nwc) | | [Breez SDK](#breez-sdk) | [Breez Liquid SDK](#breez-liquid-sdk) | [Nostr Wallet Connect](#nostr-wallet-connect-nwc) |
| [Strike](#strike) | [Eclair (ACINQ)](#eclair-acinq) | [LN.tips](#lntips) | | [Strike](#strike) | [Eclair (ACINQ)](#eclair-acinq) | [LN.tips](#lntips) |
| [Fake Wallet](#fake-wallet) | | | | [Fake Wallet](#fake-wallet) | | |
@@ -128,18 +128,32 @@ Old REST interface using [RTL c-lightning-REST](https://github.com/Ride-The-Ligh
- `SPARK_URL`: `http://10.147.17.230:9737/rpc` - `SPARK_URL`: `http://10.147.17.230:9737/rpc`
- `SPARK_TOKEN`: `secret_access_key` - `SPARK_TOKEN`: `secret_access_key`
## Spark L2 ## Spark (L2)
Self-custodial funding source using the [Spark L2](https://docs.spark.money/start/overview) network. Requires a Node.js [sidecar](https://github.com/lnbits/spark_sidecar) that bridges lnbits talking to Spark. Works in addition with any Spark-compatible seed (Wallet of Satoshi, BuhoGO, BlitzWallet). Spark L2 is a self-custodial funding source that uses a small Node.js sidecar to talk to the Spark network and expose an HTTP API. You can let LNbits run the sidecar internally, or run it yourself and point LNbits at it.
If the sidecar is started with a `mnemonic` then that mnemonic will be used. Otherwhise if a mnemonic is set for the `Spark L2` LNbits funding source then that mnemonic will be used.
### Optional tuning **Required env vars**
- `SPARK_L2_PAY_WAIT_MS`: `4000` _(payment timeout in ms)_ - `LNBITS_BACKEND_WALLET_CLASS`: `SparkL2Wallet`
- `SPARK_L2_PAY_POLL_MS`: `500` _(polling interval in ms)_
- `SPARK_L2_STREAM_KEEPALIVE_MS`: `15000` _(SSE keepalive in ms)_
### Example: run the sidecar **Internal sidecar (LNbits-managed)**
- `SPARK_L2_INTERNAL_SIDECAR_VERSION`: `0.1.1`
- `SPARK_L2_MNEMONIC`: `...` (optional; auto-generated if blank)
- `SPARK_L2_NETWORK`: `MAINNET`
Optional tuning:
- `SPARK_L2_PAY_WAIT_MS`: `4000`
- `SPARK_L2_PAY_POLL_MS`: `500`
- `SPARK_L2_STREAM_KEEPALIVE_MS`: `15000`
**External sidecar**
- `SPARK_L2_EXTERNAL_ENDPOINT`: `http://127.0.0.1:8765`
- `SPARK_L2_EXTERNAL_API_KEY`: `...` (if your sidecar requires auth)
Example: run the sidecar manually (external mode)
```bash ```bash
git clone https://github.com/lnbits/spark_sidecar.git git clone https://github.com/lnbits/spark_sidecar.git
@@ -153,7 +167,7 @@ SPARK_PAY_WAIT_MS=20000 \
node server.mjs node server.mjs
``` ```
For testing, you can generate a 12-word mnemonic at https://iancoleman.io/bip39/. Store it securely — it controls your funds. Then select Spark (L2) as the funding source in LNbits. For testing, you can generate a 12-word mnemonic at `https://iancoleman.io/bip39/`. Store it securely — it controls your funds. Then select **Spark (L2)** as the funding source in LNbits.
## LND (REST) ## LND (REST)
+3 -4
View File
@@ -292,13 +292,13 @@ class ThemesSettings(LNbitsSettings):
lnbits_qr_logo: str = Field(default="/static/images/favicon_qr_logo.png") lnbits_qr_logo: str = Field(default="/static/images/favicon_qr_logo.png")
lnbits_apple_touch_icon: str | None = Field(default=None) lnbits_apple_touch_icon: str | None = Field(default=None)
lnbits_default_reaction: str = Field(default="confettiBothSides") lnbits_default_reaction: str = Field(default="confettiBothSides")
lnbits_default_theme: str = Field(default="bitcoin") lnbits_default_theme: str = Field(default="salvador")
lnbits_default_border: str = Field(default="hard-border") lnbits_default_border: str = Field(default="hard-border")
lnbits_default_gradient: bool = Field(default=True) lnbits_default_gradient: bool = Field(default=True)
lnbits_default_bgimage: str | None = Field(default=None) lnbits_default_bgimage: str | None = Field(default=None)
lnbits_default_dark: bool = Field(default=True) lnbits_default_dark: bool = Field(default=True)
lnbits_default_card_rounded: bool = Field(default=True) lnbits_default_card_rounded: bool = Field(default=False)
lnbits_default_card_gradient: bool = Field(default=True) lnbits_default_card_gradient: bool = Field(default=False)
lnbits_default_card_shadow: bool = Field(default=False) lnbits_default_card_shadow: bool = Field(default=False)
@@ -610,7 +610,6 @@ class SparkL2FundingSource(LNbitsSettings):
spark_l2_network: str = Field(default="MAINNET") spark_l2_network: str = Field(default="MAINNET")
spark_l2_external_endpoint: str | None = Field(default="http://localhost:8765") spark_l2_external_endpoint: str | None = Field(default="http://localhost:8765")
spark_l2_external_api_key: str | None = Field(default=None) spark_l2_external_api_key: str | None = Field(default=None)
spark_l2_mnemonic: str | None = Field(default=None)
spark_l2_pay_wait_ms: int = Field(default=4000, ge=0) spark_l2_pay_wait_ms: int = Field(default=4000, ge=0)
spark_l2_pay_poll_ms: int = Field(default=500, ge=0) spark_l2_pay_poll_ms: int = Field(default=500, ge=0)
spark_l2_stream_keepalive_ms: int = Field(default=15000, ge=0) spark_l2_stream_keepalive_ms: int = Field(default=15000, ge=0)
File diff suppressed because one or more lines are too long
+10 -10
View File
File diff suppressed because one or more lines are too long
+84 -90
View File
@@ -6,7 +6,7 @@ window.localisation.en = {
funding: 'Funding', funding: 'Funding',
users: 'Users', users: 'Users',
audit: 'Audit', audit: 'Audit',
api_watch: 'API Watch', api_watch: 'Api Watch',
apps: 'Apps', apps: 'Apps',
channels: 'Channels', channels: 'Channels',
transactions: 'Transactions', transactions: 'Transactions',
@@ -271,16 +271,12 @@ window.localisation.en = {
update: 'Update', update: 'Update',
update_available: 'Update {version} available!', update_available: 'Update {version} available!',
funding_sources: 'Funding Sources', funding_sources: 'Funding Sources',
funding_source: 'Funding Source',
requires_server_restart:
'Changing these settings requires a server restart to take effect.',
funding_source_info: 'Select the active funding wallet',
latest_update: 'You are on the latest version {version}.', latest_update: 'You are on the latest version {version}.',
notifications: 'Notifications', notifications: 'Notifications',
notifications_configure: 'Configure Notifications', notifications_configure: 'Configure Notifications',
notifications_nostr_config: 'Nostr Configuration', notifications_nostr_config: 'Nostr Configuration',
notifications_enable_nostr: 'Enable Nostr', notifications_enable_nostr: 'Enable Nostr',
notifications_enable_nostr_desc: 'Send notifications over Nostr', notifications_enable_nostr_desc: 'Send notfications over Nostr',
notifications_nostr_private_key: 'Nostr Private Key', notifications_nostr_private_key: 'Nostr Private Key',
notifications_nostr_private_key_desc: notifications_nostr_private_key_desc:
'Private key (hex or nsec) to sign the messages sent to Nostr', 'Private key (hex or nsec) to sign the messages sent to Nostr',
@@ -293,7 +289,7 @@ window.localisation.en = {
notifications_telegram_config: 'Telegram Configuration', notifications_telegram_config: 'Telegram Configuration',
notifications_enable_telegram: 'Enable Telegram', notifications_enable_telegram: 'Enable Telegram',
notifications_enable_telegram_desc: 'Send notifications over Telegram', notifications_enable_telegram_desc: 'Send notfications over Telegram',
notifications_telegram_access_token: 'Access Token', notifications_telegram_access_token: 'Access Token',
notifications_telegram_access_token_desc: 'Access token for the bot', notifications_telegram_access_token_desc: 'Access token for the bot',
notifications_chat_id: 'Telegram Chat ID', notifications_chat_id: 'Telegram Chat ID',
@@ -322,15 +318,15 @@ window.localisation.en = {
notification_settings_update: 'Settings updated', notification_settings_update: 'Settings updated',
notification_settings_update_desc: notification_settings_update_desc:
'Send a notification when server settings have been updated', 'Notify when server settings have been updated',
notification_server_start_stop: 'Server Start/Stop', notification_server_start_stop: 'Server Start/Stop',
notification_server_start_stop_desc: notification_server_start_stop_desc:
'Send a notification when the server has been started/stopped', 'Notify when the server has been started/stopped',
notification_watchdog_limit: 'Watchdog Limit Notification', notification_watchdog_limit: 'Watchdog Limit Notification',
notification_watchdog_limit_desc: notification_watchdog_limit_desc:
'Send a notification when the watchdog limit has been reached (does not affect the funding source)', 'Notify when the watchdog limit has been reached (does not affect the funding source)',
notification_server_status: 'Server Status', notification_server_status: 'Server Status',
notification_server_status_desc: notification_server_status_desc:
@@ -338,31 +334,29 @@ window.localisation.en = {
notification_incoming_payment: 'Incoming Payments', notification_incoming_payment: 'Incoming Payments',
notification_incoming_payment_desc: notification_incoming_payment_desc:
'Send a notification when a wallet has received a payment above the specified amount (sats)', 'Notify when a wallet has received a payment above the specified amount (sats)',
notification_outgoing_payment: 'Outgoing Payments', notification_outgoing_payment: 'Outgoing Payments',
notification_outgoing_payment_desc: notification_outgoing_payment_desc:
'Send a notification when a wallet has sent a payment above the specified amount (sats)', 'Notify when a wallet has sent a payment above the specified amount (sats)',
notification_credit_debit: 'Credit / Debit', notification_credit_debit: 'Credit / Debit',
notification_credit_debit_desc: notification_credit_debit_desc:
'Send a notification when a wallet has been credited/debited by the superuser', 'Notify when a wallet has been credited/debited by the superuser',
notification_balance_delta_changed: 'Balance Delta Changed', notification_balance_delta_changed: 'Balance Delta Changed',
notification_balance_delta_changed_desc: notification_balance_delta_changed_desc:
'Send a notification when the difference between the node balance and the LNbits balance has changed by more than the specified amount (in sats). Set to 0 to disable. This runs every minute.', 'Notify when the difference between the node balance and the LNbits balance has changed by more than the specified amount (in sats). Set to 0 to disable. This runs every minute.',
watchdog_introduction: enable_watchdog: 'Enable Watchdog Switch',
"Watchdog is a feature that allows you to automatically switch the LNbits funding source to VoidWallet if your node balance is lower than the LNbits balance by a certain threshold. This can help prevent overspending and keep your node's funds safe.",
enable_watchdog: 'Enable Watchdog',
enable_watchdog_desc: enable_watchdog_desc:
'You will need to re-enable this manually after an update.', 'If enabled it will change your funding source to VoidWallet automatically if your balance is lower than the LNbits balance. You will need to enable manually after an update.',
watchdog_interval: 'Watchdog Check Interval', watchdog_interval: 'Watchdog Interval',
watchdog_interval_desc: watchdog_interval_desc:
'How often LNbits should check for a killswitch signal in the watchdog threshold delta value [node_balance - lnbits_balance] (in minutes).', 'How often the background task should check for a killswitch signal in the watchdog delta [node_balance - lnbits_balance] (in minutes).',
watchdog_delta: 'Watchdog Threshold Delta', watchdog_delta: 'Watchdog Delta',
watchdog_delta_desc: watchdog_delta_desc:
"The LNbit's > Node balance delta threshold. If this threshold is exceeded, the funding source is changed to VoidWallet.", 'Limit before killswitch changes funding source to VoidWallet [lnbits_balance - node_balance > delta]',
status: 'Status', status: 'Status',
notification_source: 'Notification Source', notification_source: 'Notification Source',
notification_source_label: notification_source_label:
@@ -373,12 +367,12 @@ window.localisation.en = {
releases: 'Releases', releases: 'Releases',
watchdog: 'Watchdog', watchdog: 'Watchdog',
server_logs: 'Server Logs', server_logs: 'Server Logs',
ip_blocker: 'IP Blacklist/Whitelist', ip_blocker: 'IP Blocker',
security: 'Security', security: 'Security',
security_tools: 'Security Tools', security_tools: 'Security tools',
block_access_hint: 'Block access by IP', block_access_hint: 'Block access by IP',
allow_access_hint: 'Allow access by IP (will override blocked IPs)', allow_access_hint: 'Allow access by IP (will override blocked IPs)',
enter_ip: 'Enter an IP address and press enter', enter_ip: 'Enter IP and hit enter',
rate_limiter: 'Rate Limiter', rate_limiter: 'Rate Limiter',
callback_url_rules: 'Callback URL Rules', callback_url_rules: 'Callback URL Rules',
enter_callback_url_rule: 'Enter URL rule as regex and hit enter', enter_callback_url_rule: 'Enter URL rule as regex and hit enter',
@@ -392,16 +386,14 @@ window.localisation.en = {
wallet_max_ballance: 'Wallet max balance in sats (0 to disable)', wallet_max_ballance: 'Wallet max balance in sats (0 to disable)',
wallet_limit_secs_between_trans: wallet_limit_secs_between_trans:
'Min secs between transactions per wallet (0 to disable)', 'Min secs between transactions per wallet (0 to disable)',
only_incoming_payments_allowed: 'Allow incoming payments only', only_incoming_payments_allowed: 'Only incoming payments allowed',
disable_outgoing_payments: 'Disable outgoing payments', disable_outgoing_payments: 'Disable outgoing payments',
number_of_requests: 'Number of requests to allow', number_of_requests: 'Number of requests',
number_of_requests_hint:
'Number of requests to allow per "time unit" for the rate limiter. Set to 0 to disable.',
time_unit: 'Time unit', time_unit: 'Time unit',
minute: 'Minute', minute: 'minute',
settings: 'Settings', settings: 'Settings',
second: 'Second', second: 'second',
hour: 'Hour', hour: 'hour',
disable_server_log: 'Disable Server Log', disable_server_log: 'Disable Server Log',
enable_server_log: 'Enable Server Log', enable_server_log: 'Enable Server Log',
coming_soon: 'Feature coming soon', coming_soon: 'Feature coming soon',
@@ -541,30 +533,33 @@ window.localisation.en = {
create_ticker_converter: 'Create Currency Ticker Converter', create_ticker_converter: 'Create Currency Ticker Converter',
enable_audit: 'Enable Audit', enable_audit: 'Enable Audit',
recommended: 'Recommended', recommended: 'Recommended',
audit_desc: 'Log HTTP requests according to the filters specified below.', audit_desc: 'Record HTTP requests according with the specified filters',
audit_record_req: 'Log Request Body', audit_record_req: 'Record Request Body',
audit_record_warning: 'Warning!', audit_record_warning: 'Warning: ',
audit_record_req_warning_1: 'Sensitive data (like passwords) will be logged.', audit_record_req_warning_1:
audit_record_req_warning_2: 'confidential data (like passwords) will be logged.',
'The request body can be large. This can fill up your logs quickly.', audit_record_req_warning_2: 'the request body can have large size.',
audit_record_use: 'Use this with caution!', audit_record_use: 'Use it with caution.',
audit_ip: 'Log IP Address', audit_ip: 'Record IP Address',
audit_ip_desc: 'Log the IP address of users making requests to LNbits.', audit_ip_desc: 'Record the IP address of the client',
audit_path_params: 'Log Path Parameters', audit_path_params: 'Record Path Parameters',
audit_query_params: 'Log Query Parameters', audit_query_params: 'Record Query Parameters',
audit_http_methods: 'Include HTTP Methods', audit_http_methods: 'Include HTTP Methods',
audit_http_methods_hint: audit_http_methods_hint:
'List of HTTP methods to be logged. No value means all methods will be logged.', 'List of HTTP methods to be included. Empty lists means all.',
audit_http_methods_label: 'HTTP Methods to Log', audit_http_methods_label: 'HTTP Methods',
audit_resp_codes: 'Include HTTP Response Codes',
audit_resp_codes_hint: audit_resp_codes_hint:
'List of HTTP codes to be included (regex match). Empty lists means all. Eg: 4.*, 5.*', 'List of HTTP codes to be included (regex match). Empty lists means all. Eg: 4.*, 5.*',
audit_resp_codes_label: 'HTTP Response Codes to Log (regex)', audit_resp_codes_label: 'HTTP Response code (regex)',
audit_paths: 'Include Paths',
audit_paths_hint: audit_paths_hint:
'List of paths to be included (regex match). Empty list means all.', 'List of paths to be included (regex match). Empty list means all.',
audit_paths_label: 'HTTP Paths to Log (regex)', audit_paths_label: 'HTTP Path (regex)',
audit_paths_exclude: 'Exclude Paths',
audit_paths_exclude_hint: audit_paths_exclude_hint:
'List of paths to be excluded (regex match). Empty list means none.', 'List of paths to be excluded (regex match). Empty list means none.',
audit_paths_exclude_label: 'HTTP Paths to Exclude from Logging (regex)', audit_paths_exclude_label: 'HTTP Path (regex)',
exchange_providers: 'Exchange Providers', exchange_providers: 'Exchange Providers',
admin_extensions: 'Admin Extensions', admin_extensions: 'Admin Extensions',
admin_extensions_label: 'Admin extensions', admin_extensions_label: 'Admin extensions',
@@ -584,16 +579,16 @@ window.localisation.en = {
misc_disable_extensions_builder_label: misc_disable_extensions_builder_label:
'Enable Extensions Builder for non admin users.', 'Enable Extensions Builder for non admin users.',
misc_hide_api: 'Hide API', misc_hide_api: 'Hide API',
misc_hide_api_label: 'Hides wallet API, extensions can choose to honor', misc_hide_api_label: 'Hides wallet api, extensions can choose to honor',
wallets_management: 'Wallets Management', wallets_management: 'Wallets Management',
funding_source_info: 'Funding Source Information', funding_source_info: 'Funding Source Info',
funding_source: 'Funding source: {wallet_class}', funding_source: 'Funding Source: {wallet_class}',
node_balance: 'Node balance: {balance} sats', node_balance: 'Node Balance: {balance} sats',
lnbits_balance: 'LNbits balance: {balance} sats', lnbits_balance: 'LNbits Balance: {balance} sats',
funding_reserve_percent: 'Funding reserve percentage: {percent} %', funding_reserve_percent: 'Reserve Percent: {percent} %',
node_management: 'Node Management', node_management: 'Node Management',
node_management_not_supported: node_management_not_supported:
'Node management is not supported by the active funding source', 'Node Management not supported by active funding source',
toggle_node_ui: 'Node UI', toggle_node_ui: 'Node UI',
toggle_public_node_ui: 'Public Node UI', toggle_public_node_ui: 'Public Node UI',
toggle_transactions_node_ui: 'Transactions Tab (Disable on large CLN nodes)', toggle_transactions_node_ui: 'Transactions Tab (Disable on large CLN nodes)',
@@ -609,15 +604,16 @@ window.localisation.en = {
payment_wait_time_tooltip: payment_wait_time_tooltip:
'Controls how long LNbits waits for an outgoing payment attempt to confirm before marking it as pending. Higher values help when paying slow-settling invoices (e.g., HODL invoices, Boltz). The payment will be rechecked later and updated automatically or manually.', 'Controls how long LNbits waits for an outgoing payment attempt to confirm before marking it as pending. Higher values help when paying slow-settling invoices (e.g., HODL invoices, Boltz). The payment will be rechecked later and updated automatically or manually.',
server_management: 'Server Management', server_management: 'Server Management',
base_url_label: 'Base URL of the server', base_url: 'Base URL',
base_url_label: 'Static/Base url for the server',
authentication: 'Authentication', authentication: 'Authentication',
auth_token_expiry_label: 'Token expiry (minutes)', auth_token_expiry_label: 'Token expire minutes',
auth_token_expiry_hint: 'Time in minutes until the token expires', auth_token_expiry_hint: 'Time in minutes until the token expires',
auth_authentication_cache_label: 'Cache time (minutes)', auth_authentication_cache_label: 'Cache time (minutes)',
auth_authentication_cache_hint: auth_authentication_cache_hint:
'Time in minutes to cache successful authentication (0 to disable)', 'Time in minutes to cache successful authentication (0 to disable)',
auth_allowed_methods_label: 'Allowed authorization methods', auth_allowed_methods_label: 'Allowed authorization methods',
auth_allowed_methods_hint: 'Select allowed authorization methods', auth_allowed_methods_hint: 'Select authorization methods',
auth_nostr_label: 'Nostr Request URL', auth_nostr_label: 'Nostr Request URL',
auth_nostr_hint: 'Absolute URL that the clients will use to login.', auth_nostr_hint: 'Absolute URL that the clients will use to login.',
auth_google_ci_label: 'Google Client ID', auth_google_ci_label: 'Google Client ID',
@@ -637,27 +633,31 @@ window.localisation.en = {
auth_keycloak_custom_icon_label: 'Keycloak Custom Icon (URL)', auth_keycloak_custom_icon_label: 'Keycloak Custom Icon (URL)',
currency_settings: 'Currency Settings', currency_settings: 'Currency Settings',
allowed_currencies: 'Allowed Currencies', allowed_currencies: 'Allowed Currencies',
allowed_currencies_hint: allowed_currencies_hint: 'Limit the number of available fiat currencies',
'Set the allowed fiat currencies for the exchange features', default_account_currency: 'Default Account Currency',
default_account_currency: 'Default Accounting Currency', default_account_currency_hint: 'Default currency for accounting',
default_account_currency_hint:
'The default currency to use for accounting features.',
min_incoming_payment_amount: 'Min Incoming Payment Amount', min_incoming_payment_amount: 'Min Incoming Payment Amount',
min_incoming_payment_amount_desc: min_incoming_payment_amount_desc:
'Minimum amount allowed for generating an invoice', 'Minimum amount allowed for generating an invoice',
max_incoming_payment_amount: 'Maximum Incoming Payment Amount', max_incoming_payment_amount: 'Max Incoming Payment Amount',
max_incoming_payment_amount_desc: max_incoming_payment_amount_desc:
'Maximum amount allowed when generating an invoice', 'Maximum amount allowed for generating an invoice',
max_outgoing_payment_amount: 'Maximum Outgoing Payment Amount', max_outgoing_payment_amount: 'Max Outgoing Payment Amount',
max_outgoing_payment_amount_desc: max_outgoing_payment_amount_desc:
'Maximum amount allowed when making a payment', 'Maximum amount allowed for making a payment',
service_fees: 'Service Fees',
service_fee: 'Service Fee', service_fee: 'Service Fee',
service_fee_label: 'Service Fee Charged Per Transaction', service_fee_label: 'Service fee (%)',
service_fee_max_label: 'Maximum Service Fee Limit', service_fee_hint: 'Fee charged per tx (%)',
fee_wallet_label: 'Service Fee Wallet ID', service_fee_max: 'Service Fee Max',
fee_wallet_hint: 'The ID of the wallet to which to send service funds', service_fee_max_label: 'Service fee max (sats)',
disable_fee: 'Disable Service Fees for Internal Payments', service_fee_max_hint: 'Max service fee to charge in (sats)',
fee_wallet: 'Fee Wallet',
fee_wallet_label: 'Fee wallet (wallet ID)',
fee_wallet_hint: 'Wallet ID to send funds to',
disable_fee: 'Disable Fee',
disable_fee_internal: 'Disable Service Fee for Internal Payments',
disable_fee_internal_desc:
'Disable Service Fee for Internal Lightning Payments',
ui_management: 'UI Management', ui_management: 'UI Management',
ui_site_title: 'Site Title', ui_site_title: 'Site Title',
ui_changing_remove_lnbits_elements: ui_changing_remove_lnbits_elements:
@@ -670,7 +670,6 @@ window.localisation.en = {
ui_site_description_hint: 'Use plain text, Markdown, or raw HTML', ui_site_description_hint: 'Use plain text, Markdown, or raw HTML',
ui_default_wallet_name: 'Default Wallet Name', ui_default_wallet_name: 'Default Wallet Name',
ui_default_theme: 'Default Theme', ui_default_theme: 'Default Theme',
wallet_featured_button_title: 'Wallet - Featured Button',
wallet_featured_button_label: 'Wallet Featured Button Label', wallet_featured_button_label: 'Wallet Featured Button Label',
wallet_featured_button_label_hint: wallet_featured_button_label_hint:
'Show featured button on the wallet homepage', 'Show featured button on the wallet homepage',
@@ -679,38 +678,33 @@ window.localisation.en = {
'On click the button will open this URL. Leave empty to hide the button.', 'On click the button will open this URL. Leave empty to hide the button.',
wallet_featured_button_icon: 'Featured Button Icon', wallet_featured_button_icon: 'Featured Button Icon',
wallet_featured_button_icon_hint: wallet_featured_button_icon_hint:
'Icon shown on the featured button (Quasar icon name e.g. "bolt")', 'Icon shown on the featured button (check quasar icons)',
lnbits_wallet: 'LNbits wallet', lnbits_wallet: 'LNbits wallet',
denomination: 'Denomination', denomination: 'Denomination',
denomination_hint: 'The name for the FakeWallet token', denomination_hint: 'The name for the FakeWallet token',
denomination_error: 'Denomination must be 3 characters, or `sats`', denomination_error: 'Denomination must be 3 characters, or `sats`',
ui_qr_code_logo: 'QR Code/Favicon Logo', ui_qr_code_logo: 'QR Code/Favicon Logo',
ui_qr_code_logo_hint: 'QR code icon and favicon logo URL', ui_qr_code_logo_hint: 'QR code and favicon logo url',
ui_apple_touch_icon: 'Apple Touch Icon', ui_apple_touch_icon: 'Apple Touch Icon',
ui_apple_touch_icon_hint: 'Apple touch icon URL', ui_apple_touch_icon_hint: 'Apple touch icon url',
ui_custom_image: 'Custom Image', ui_custom_image: 'Custom Image',
ui_custom_image_label: 'URL to custom image', ui_custom_image_label: 'URL to custom image',
ui_custom_image_hint: ui_custom_image_hint: 'Image showed at homepage/login',
'This image is shown on the LNbits homepage and login screen.', ui_custom_badge: 'Custom Badge',
ui_custom_badge_title: 'Custom Badge Settings',
ui_custom_badge_desc: 'Show a custom badge in the header of LNbits',
ui_custom_badge: 'Custom Badge Text',
ui_custom_badge_label: "Custom Badge 'USE WITH CAUTION'", ui_custom_badge_label: "Custom Badge 'USE WITH CAUTION'",
ui_custom_badge_color_label: 'Custom Badge Color', ui_custom_badge_color_label: 'Custom Badge Color',
themes: 'Themes', themes: 'Themes',
themes_hint: 'Choose themes available for users', themes_hint: 'Choose themes available for users',
custom_logo: 'Custom Logo', custom_logo: 'Custom Logo',
custom_logo_hint: 'URL to logo image', custom_logo_hint: 'URL to logo image',
ad_space_section_title: 'Advertisement Space', ad_space_title: 'Ad Space Title',
ad_space_section_desc: ad_space_title_label: 'Supported by',
'Configure the advertisement space on the wallet sidebar.',
ad_space_title: 'Advertisement Space Title',
ad_space_title_hint: 'Title shown above the advertisement space',
ad_slots: 'Advertisement Slots', ad_slots: 'Advertisement Slots',
ad_slots_hint: ad_slots_hint:
'Advertisement image filepaths in CSV format, extensions can choose to honor. Format: url;img_light_url;img_dark_url, url..', 'Ad url and image filepaths in CSV format, extensions can choose to honor',
ads_enabled: 'Enable Advertisement', ad_slots_label: 'url;img_light_url;img_dark_url, url...',
ads_disabled: 'Disabled Advertisement', ads_enabled: 'Ads Enabled',
ads_disabled: 'Ads Disabled',
user_management: 'User Management', user_management: 'User Management',
admin_users: 'Admin Users', admin_users: 'Admin Users',
admin_users_hint: 'Users with admin privileges', admin_users_hint: 'Users with admin privileges',
@@ -234,12 +234,7 @@ window.app.component('lnbits-admin-funding-sources', {
{ {
spark_l2_external_endpoint: { spark_l2_external_endpoint: {
label: 'External Sidecar Endpoint', label: 'External Sidecar Endpoint',
hint: 'Make sure to also specify the API key if your sidecar requires authentication.', hint: 'If specified then this endpoint will be used instead of the internal sidecar. Make sure to also specify the API key if your sidecar requires authentication.',
value: ''
},
spark_l2_mnemonic: {
label: 'External Sidecar Mnemonic',
hint: 'Mnemonic for the Spark wallet on the external sidecar. Required if the side car does not have its own mnemonic.',
value: '' value: ''
}, },
spark_l2_external_api_key: { spark_l2_external_api_key: {
@@ -17,13 +17,6 @@ window.app.component('lnbits-manage-wallet-list', {
} else { } else {
this.activeWalletId = null this.activeWalletId = null
} }
},
'g.user.wallets': {
handler() {
this.paymentEvents()
},
deep: true,
immediate: true
} }
}, },
created() { created() {
-16
View File
@@ -131,22 +131,6 @@ window._lnbitsUtils = {
currency: currency || 'sat' currency: currency || 'sat'
}).format(value) }).format(value)
}, },
getCurrencySymbol(currency) {
const code = (currency || '').toUpperCase()
if (code === 'BTC' || code === 'XBT' || code === 'SAT' || code === 'SATS') {
return '₿'
}
try {
const parts = new Intl.NumberFormat(window.i18n.global.locale, {
style: 'currency',
currency: code
}).formatToParts(0)
const symbolPart = parts.find(part => part.type === 'currency')
return symbolPart?.value || code || '¤'
} catch (e) {
return code || '¤'
}
},
formatSat(value) { formatSat(value) {
return new Intl.NumberFormat(window.i18n.global.locale).format(value) return new Intl.NumberFormat(window.i18n.global.locale).format(value)
}, },
@@ -3,6 +3,9 @@
<h6 class="q-my-none q-mb-sm">Assets</h6> <h6 class="q-my-none q-mb-sm">Assets</h6>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-3"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('max_asset_size_mb')"></span>
</p>
<q-input <q-input
filled filled
type="number" type="number"
@@ -15,6 +18,9 @@
</div> </div>
<div class="col-12 col-md-9"> <div class="col-12 col-md-9">
<p>
<span v-text="$t('assets_allowed_mime_types')"></span>
</p>
<q-input <q-input
filled filled
v-model.number="newAllowedAssetMimeType" v-model.number="newAllowedAssetMimeType"
@@ -50,8 +56,11 @@
</div> </div>
<q-separator class="q-mb-lg q-mt-sm"></q-separator> <q-separator class="q-mb-lg q-mt-sm"></q-separator>
<h6 class="q-my-none q-mb-sm">Thumbnails</h6> <h6 class="q-my-none q-mb-sm">Thumbnails</h6>
<div class="row q-col-gutter-md q-my-lg"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-4"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('thumbnail_width')"></span>
</p>
<q-input <q-input
filled filled
type="number" type="number"
@@ -62,7 +71,10 @@
:hint="$t('thumbnail_width_desc')" :hint="$t('thumbnail_width_desc')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('thumbnail_height')"></span>
</p>
<q-input <q-input
filled filled
type="number" type="number"
@@ -73,7 +85,10 @@
:hint="$t('thumbnail_height_desc')" :hint="$t('thumbnail_height_desc')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('thumbnail_format')"></span>
</p>
<q-input <q-input
filled filled
v-model.number="formData.lnbits_asset_thumbnail_format" v-model.number="formData.lnbits_asset_thumbnail_format"
@@ -86,6 +101,9 @@
<h6 class="q-my-none q-mb-sm">Users</h6> <h6 class="q-my-none q-mb-sm">Users</h6>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-3"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('max_assets_per_user')"></span>
</p>
<q-input <q-input
filled filled
type="number" type="number"
@@ -97,6 +115,9 @@
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-9"> <div class="col-12 col-md-9">
<p>
<span v-text="$t('assets_no_limit_users')"></span>
</p>
<q-input <q-input
filled filled
v-model="newNoLimitUser" v-model="newNoLimitUser"
+10 -4
View File
@@ -32,7 +32,7 @@
</div> </div>
<q-separator class="q-mb-lg q-mt-sm"></q-separator> <q-separator class="q-mb-lg q-mt-sm"></q-separator>
<div class="row"> <div class="row">
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-3 col-sm-12 q-pr-sm">
<q-item tag="label" v-ripple> <q-item tag="label" v-ripple>
<q-item-section avatar> <q-item-section avatar>
<q-toggle <q-toggle
@@ -62,7 +62,7 @@
</q-item-section> </q-item-section>
</q-item> </q-item>
</div> </div>
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-3 col-sm-12 q-pr-sm">
<q-item tag="label" v-ripple> <q-item tag="label" v-ripple>
<q-item-section avatar> <q-item-section avatar>
<q-toggle <q-toggle
@@ -83,7 +83,7 @@
</q-item-section> </q-item-section>
</q-item> </q-item>
</div> </div>
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-3 col-sm-12 q-pr-sm">
<q-item tag="label" v-ripple> <q-item tag="label" v-ripple>
<q-item-section avatar> <q-item-section avatar>
<q-toggle <q-toggle
@@ -104,7 +104,7 @@
</q-item-section> </q-item-section>
</q-item> </q-item>
</div> </div>
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-3 col-sm-12 q-pr-sm">
<q-item tag="label" v-ripple> <q-item tag="label" v-ripple>
<q-item-section avatar> <q-item-section avatar>
<q-toggle <q-toggle
@@ -129,6 +129,7 @@
<q-separator class="q-mb-xl q-mt-sm"></q-separator> <q-separator class="q-mb-xl q-mt-sm"></q-separator>
<div class="row q-mb-lg"> <div class="row q-mb-lg">
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-6 col-sm-12 q-pr-sm">
<p><span v-text="$t('audit_http_methods')"></span></p>
<q-select <q-select
filled filled
v-model="formData.lnbits_audit_http_methods" v-model="formData.lnbits_audit_http_methods"
@@ -147,6 +148,7 @@
></q-select> ></q-select>
</div> </div>
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-6 col-sm-12 q-pr-sm">
<p><span v-text="$t('audit_resp_codes')"></span></p>
<q-input <q-input
class="q-mb-md" class="q-mb-md"
filled filled
@@ -175,6 +177,7 @@
<div class="row"> <div class="row">
<div class="col-md-6 col-sm-12 q-pr-sm"> <div class="col-md-6 col-sm-12 q-pr-sm">
<p><span v-text="$t('audit_paths')"></span></p>
<q-input <q-input
class="q-mb-md" class="q-mb-md"
filled filled
@@ -201,6 +204,9 @@
<br /> <br />
</div> </div>
<div class="col-md-6 col-sm-12"> <div class="col-md-6 col-sm-12">
<p>
<span v-text="$t('audit_paths_exclude')"></span>
</p>
<q-input <q-input
class="q-mb-md" class="q-mb-md"
filled filled
@@ -19,7 +19,6 @@
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<q-input <q-input
class="q-mb-md"
filled filled
v-model="formData.lnbits_exchange_history_refresh_interval_seconds" v-model="formData.lnbits_exchange_history_refresh_interval_seconds"
type="number" type="number"
@@ -137,7 +137,7 @@
:hint="$t('extension_builder_manifest_url_hint')" :hint="$t('extension_builder_manifest_url_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-6 q-pb-md"> <div class="col-12 col-md-6">
<p> <p>
<span v-text="$t('reviews_url')"></span> <span v-text="$t('reviews_url')"></span>
</p> </p>
@@ -128,7 +128,7 @@
</ul> </ul>
</q-card-section> </q-card-section>
</q-expansion-item> </q-expansion-item>
<q-expansion-item :label="$t('service_fees')"> <q-expansion-item :label="$t('service_fee')">
<q-card-section> <q-card-section>
<div class="row"> <div class="row">
<div class="col-md-4 col-sm-12"> <div class="col-md-4 col-sm-12">
@@ -140,6 +140,7 @@
v-model="formData.stripe_limits.service_fee_percent" v-model="formData.stripe_limits.service_fee_percent"
@update:model-value="formData.touch = null" @update:model-value="formData.touch = null"
:label="$t('service_fee_label')" :label="$t('service_fee_label')"
:hint="$t('service_fee_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-md-4 col-sm-12"> <div class="col-md-4 col-sm-12">
@@ -150,7 +151,8 @@
min="0" min="0"
v-model="formData.stripe_limits.service_max_fee_sats" v-model="formData.stripe_limits.service_max_fee_sats"
@update:model-value="formData.touch = null" @update:model-value="formData.touch = null"
:label="$t('service_fee_max_label')" :label="$t('service_fee_max')"
:hint="$t('service_fee_max_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-md-4 col-sm-12"> <div class="col-md-4 col-sm-12">
@@ -165,11 +165,6 @@
<h6 class="q-mt-lg q-mb-sm"> <h6 class="q-mt-lg q-mb-sm">
<p v-text="$t('watchdog')"></p> <p v-text="$t('watchdog')"></p>
</h6> </h6>
<div class="row q-col-gutter-md">
<div class="col-12">
<p v-text="$t('watchdog_introduction')"></p>
</div>
</div>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<q-item tag="label" v-ripple> <q-item tag="label" v-ripple>
@@ -244,7 +239,6 @@
<q-input <q-input
filled filled
v-model="formData.lnbits_watchdog_delta" v-model="formData.lnbits_watchdog_delta"
:suffix="$t('sats')"
type="number" type="number"
/> />
</q-item-section> </q-item-section>
@@ -12,14 +12,11 @@
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<p> <p>Active Funding<small> (Requires server restart)</small></p>
<span v-text="$t('funding_source')"></span>
<small><span v-text="$t('requires_server_restart')"></span></small>
</p>
<q-select <q-select
filled filled
v-model="formData.lnbits_backend_wallet_class" v-model="formData.lnbits_backend_wallet_class"
:hint="$t('funding_source_info')" hint="Select the active funding wallet"
:options="sortedAllowedFundingSources" :options="sortedAllowedFundingSources"
:option-label="item => getFundingSourceLabel(item)" :option-label="item => getFundingSourceLabel(item)"
></q-select> ></q-select>
@@ -1,10 +1,11 @@
<template id="lnbits-admin-security"> <template id="lnbits-admin-security">
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<h6 class="q-my-none q-mb-sm"> <h6 class="q-my-none">
<span v-text="$t('server_management')"></span> <span v-text="$t('server_management')"></span>
</h6> </h6>
<div class="row"> <div class="row">
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<p><span v-text="$t('base_url')"></span></p>
<q-input <q-input
filled filled
v-model.number="formData.lnbits_baseurl" v-model.number="formData.lnbits_baseurl"
@@ -16,7 +17,7 @@
<h6 class="q-my-none q-mb-sm"> <h6 class="q-my-none q-mb-sm">
<span v-text="$t('authentication')"></span> <span v-text="$t('authentication')"></span>
</h6> </h6>
<div class="row q-col-gutter-sm q-mb-md"> <div class="row q-col-gutter-sm">
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<q-input <q-input
filled filled
@@ -304,7 +305,6 @@
type="number" type="number"
v-model.number="formData.lnbits_rate_limit_no" v-model.number="formData.lnbits_rate_limit_no"
:label="$t('number_of_requests')" :label="$t('number_of_requests')"
:hint="$t('number_of_requests_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
+26 -10
View File
@@ -38,11 +38,14 @@
</div> </div>
<q-separator class="q-mb-lg q-mt-sm"></q-separator> <q-separator class="q-mb-lg q-mt-sm"></q-separator>
<h6 class="q-my-none q-mb-sm"> <h6 class="q-my-none">
<span v-text="$t('payments')"></span> <span v-text="$t('payments')"></span>
</h6> </h6>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-4"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('max_outgoing_payment_amount')"></span>
</p>
<q-input <q-input
filled filled
type="number" type="number"
@@ -54,7 +57,10 @@
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-3">
<p>
<span v-text="$t('max_incoming_payment_amount')"></span>
</p>
<q-input <q-input
filled filled
type="number" type="number"
@@ -69,7 +75,7 @@
</div> </div>
<q-separator class="q-mb-lg q-mt-sm"></q-separator> <q-separator class="q-mb-lg q-mt-sm"></q-separator>
<h6 class="q-my-none q-mb-sm"> <h6 class="q-my-none">
<span v-text="$t('wallet_limiter')"></span> <span v-text="$t('wallet_limiter')"></span>
</h6> </h6>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
@@ -107,32 +113,35 @@
</div> </div>
<q-separator class="q-mb-lg q-mt-sm"></q-separator> <q-separator class="q-mb-lg q-mt-sm"></q-separator>
<h6 class="q-my-none q-mb-sm"> <h6 class="q-my-none">
<span v-text="$t('service_fees')"></span> <span v-text="$t('service_fee')"></span>
</h6> </h6>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-4"> <div class="col-12 col-md-6">
<p><span v-text="$t('service_fee')"></span></p>
<q-input <q-input
filled filled
type="number" type="number"
v-model.number="formData.lnbits_service_fee" v-model.number="formData.lnbits_service_fee"
:label="$t('service_fee_label')" :label="$t('service_fee_label')"
step="0.1" step="0.1"
:suffix="'%'" :hint="$t('service_fee_hint')"
></q-input> ></q-input>
<br /> <br />
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-6">
<p><span v-text="$t('service_fee_max')"></span></p>
<q-input <q-input
filled filled
type="number" type="number"
v-model.number="formData.lnbits_service_fee_max" v-model.number="formData.lnbits_service_fee_max"
:label="$t('service_fee_max_label')" :label="$t('service_fee_max_label')"
:suffix="$t('sats')" :hint="$t('service_fee_max_hint')"
></q-input> ></q-input>
<br /> <br />
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<p><span v-text="$t('fee_wallet')"></span></p>
<q-input <q-input
filled filled
v-model="formData.lnbits_service_fee_wallet" v-model="formData.lnbits_service_fee_wallet"
@@ -142,9 +151,16 @@
<br /> <br />
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<p>
<span v-text="$t('disable_fee_internal')"></span>
</p>
<q-item tag="label" v-ripple> <q-item tag="label" v-ripple>
<q-item-section> <q-item-section>
<q-item-label v-text="$t('disable_fee')"></q-item-label> <q-item-label v-text="$t('disable_fee')"></q-item-label>
<q-item-label
caption
v-text="$t('disable_fee_internal_desc')"
></q-item-label>
</q-item-section> </q-item-section>
<q-item-section avatar> <q-item-section avatar>
<q-toggle <q-toggle
@@ -6,7 +6,8 @@
<br /> <br />
<div> <div>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-6"> <div class="col-12 col-md-5">
<p><span v-text="$t('ui_site_title')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
@@ -17,7 +18,8 @@
></q-input> ></q-input>
<br /> <br />
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-5">
<p><span v-text="$t('ui_site_tagline')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
@@ -26,9 +28,7 @@
></q-input> ></q-input>
<br /> <br />
</div> </div>
</div> <div class="col-12 col-md-2 q-mt-xl">
<div class="row q-col-gutter-md">
<div class="col-12 col-md-12">
<q-toggle <q-toggle
:tip="$t('ui_toggle_elements_tip')" :tip="$t('ui_toggle_elements_tip')"
v-model="formData.lnbits_show_home_page_elements" v-model="formData.lnbits_show_home_page_elements"
@@ -40,66 +40,78 @@
></q-toggle> ></q-toggle>
</div> </div>
</div> </div>
<div>
<p>
<span v-text="$t('ui_site_description')"></span>
</p>
<q-input
v-model="formData.lnbits_site_description"
filled
type="textarea"
:hint="$t('ui_site_description_hint')"
/>
</div>
<br />
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12">
<q-input
v-model="formData.lnbits_site_description"
filled
type="textarea"
:label="$t('ui_site_description')"
:hint="$t('ui_site_description_hint')"
/>
</div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<p>
<span v-text="$t('ui_default_wallet_name')"></span>
</p>
<q-input <q-input
filled filled
type="text" type="text"
v-model="formData.lnbits_default_wallet_name" v-model="formData.lnbits_default_wallet_name"
:label="$t('ui_default_wallet_name')" :label="$t('lnbits_wallet')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<p><span v-text="$t('ui_qr_code_logo')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
v-model="formData.lnbits_qr_logo" v-model="formData.lnbits_qr_logo"
:label="$t('ui_qr_code_logo')" label="https://example.com/image.svg"
:hint="$t('ui_qr_code_logo_hint')" :hint="$t('ui_qr_code_logo_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<p><span v-text="$t('ui_apple_touch_icon')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
v-model="formData.lnbits_apple_touch_icon" v-model="formData.lnbits_apple_touch_icon"
:label="$t('ui_apple_touch_icon')" label="https://example.com/image.png"
:hint="$t('ui_apple_touch_icon_hint')" :hint="$t('ui_apple_touch_icon_hint')"
></q-input> ></q-input>
</div> </div>
</div> </div>
<br />
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-12">
<p><span v-text="$t('wallet_featured_button_title')"></span></p>
</div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<p>
<span v-text="$t('wallet_featured_button_label')"></span>
</p>
<q-input <q-input
filled filled
type="text" type="text"
v-model="formData.lnbits_wallet_featured_button_label" v-model="formData.lnbits_wallet_featured_button_label"
:label="$t('wallet_featured_button_label')" label="Loop to Onchain"
:hint="$t('wallet_featured_button_label_hint')" :hint="$t('wallet_featured_button_label_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<p><span v-text="$t('wallet_featured_button_url')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
v-model="formData.lnbits_wallet_featured_button_url" v-model="formData.lnbits_wallet_featured_button_url"
:label="$t('wallet_featured_button_url')" label="/boltz"
:hint="$t('wallet_featured_button_url_hint')" :hint="$t('wallet_featured_button_url_hint')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-4"> <div class="col-12 col-md-4">
<p><span v-text="$t('wallet_featured_button_icon')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
@@ -109,27 +121,21 @@
></q-input> ></q-input>
</div> </div>
</div> </div>
<div class="row q-col-gutter-md q-mt-md"> <div class="row q-col-gutter-md q-mt-md">
<div class="col-12 col-md-12"> <div class="col-12 col-md-6">
<h6 class="q-my-sm"> <p><span v-text="$t('ui_custom_badge')"></span></p>
<span v-text="$t('ui_custom_badge_title')"></span>
</h6>
<p class="q-mb-none">
<span v-text="$t('ui_custom_badge_desc')"></span>
</p>
</div>
<div class="col-12">
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-6"> <div class="col-12 col-md-8">
<q-input <q-input
filled filled
type="text" type="text"
tip="Custom Badge" tip="Custom Badge"
v-model.trim="formData.lnbits_custom_badge" v-model.trim="formData.lnbits_custom_badge"
:label="$t('ui_custom_badge')" :label="$t('ui_custom_badge_label')"
></q-input> ></q-input>
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-4">
<q-select <q-select
filled filled
v-model="formData.lnbits_custom_badge_color" v-model="formData.lnbits_custom_badge_color"
@@ -139,8 +145,8 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-12"> <div class="col-12 col-md-6">
<h6 class="q-my-sm"><span v-text="$t('ui_custom_image')"></span></h6> <p><span v-text="$t('ui_custom_image')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
@@ -151,8 +157,10 @@
></q-input> ></q-input>
</div> </div>
</div> </div>
<br />
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<p><span v-text="$t('themes')"></span></p>
<q-select <q-select
filled filled
v-model="formData.lnbits_theme_options" v-model="formData.lnbits_theme_options"
@@ -164,26 +172,41 @@
<br /> <br />
</div> </div>
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<p><span v-text="$t('custom_logo')"></span></p>
<q-input <q-input
filled filled
type="text" type="text"
v-model="formData.lnbits_custom_logo" v-model="formData.lnbits_custom_logo"
:label="$t('custom_logo')" label="https://example.com/image.png"
:hint="$t('custom_logo_hint')" :hint="$t('custom_logo_hint')"
></q-input> ></q-input>
<br /> <br />
</div> </div>
</div> </div>
<div class="row q-col-gutter-md"> <div class="row q-col-gutter-md">
<div class="col-12 col-md-12"> <div class="col-12 col-md-6">
<h6 class="q-my-sm"> <p><span v-text="$t('ad_space_title')"></span></p>
<span v-text="$t('ad_space_section_title')"></span> <q-input
</h6> filled
<p class="q-my-none"> type="text"
<span v-text="$t('ad_space_section_desc')"></span> v-model="formData.lnbits_ad_space_title"
</p> :label="$t('ad_space_title_label')"
></q-input>
<br />
</div> </div>
<div class="col-12 col-md-12"> <div class="col-12 col-md-6">
<p><span v-text="$t('ad_slots')"></span></p>
<q-input
class="q-mb-md"
filled
v-model="formData.lnbits_ad_space"
type="text"
:label="$t('ad_slots_label')"
:hint="$t('ad_slots_hint')"
><q-tooltip>
format {url};{img-light};{img-dark},{url};{img-light};{img-dark}"
</q-tooltip>
</q-input>
<q-toggle <q-toggle
v-model="formData.lnbits_ad_space_enabled" v-model="formData.lnbits_ad_space_enabled"
:label=" :label="
@@ -192,30 +215,8 @@
: $t('ads_disabled') : $t('ads_disabled')
" "
/> />
</div>
<div class="col-12 col-md-6">
<q-input
filled
type="text"
v-model="formData.lnbits_ad_space_title"
:label="$t('ad_space_title')"
:hint="$t('ad_space_title_hint')"
></q-input>
<br /> <br />
</div> </div>
<div class="col-12 col-md-6">
<q-input
class="q-mb-md"
filled
v-model="formData.lnbits_ad_space"
type="text"
:label="$t('ad_slots')"
:hint="$t('ad_slots_hint')"
><q-tooltip>
format {url};{img-light};{img-dark},{url};{img-light};{img-dark}"
</q-tooltip>
</q-input>
</div>
</div> </div>
<div class="row q-col-gutter-md q-my-md"> <div class="row q-col-gutter-md q-my-md">
<div class="col-12" v-text="$t('ui_default_theme')"></div> <div class="col-12" v-text="$t('ui_default_theme')"></div>
@@ -27,9 +27,12 @@
></q-btn> ></q-btn>
<q-toolbar-title> <q-toolbar-title>
<q-btn flat no-caps dense class="q-mr-sm" size="lg" type="a" href="/"> <q-btn flat no-caps dense class="q-mr-sm" size="lg" type="a" href="/">
<q-avatar v-if="g.settings.customLogo" height="30px"> <q-img
<img alt="Logo" :src="g.settings.customLogo" /> v-if="customLogo"
</q-avatar> height="30px"
alt="Logo"
:src="customLogo"
></q-img>
<span v-else-if="g.settings.siteTitle == 'LNbits'" <span v-else-if="g.settings.siteTitle == 'LNbits'"
><strong>LN</strong>bits</span ><strong>LN</strong>bits</span
> >
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -204,7 +204,7 @@
</q-card> </q-card>
</div> </div>
<div <div
v-show="!g.mobileSimple || !$q.screen.lt.md" v-if="!g.mobileSimple || !$q.screen.lt.md"
class="col-12 col-md-5 q-gutter-y-md" class="col-12 col-md-5 q-gutter-y-md"
> >
<lnbits-wallet-extra <lnbits-wallet-extra
+1 -35
View File
@@ -8,8 +8,6 @@ from typing import Any, cast
import httpx import httpx
from bolt11 import decode as bolt11_decode from bolt11 import decode as bolt11_decode
from coincurve.keys import PrivateKey
from embit.bip39 import mnemonic_from_bytes, mnemonic_is_valid
from loguru import logger from loguru import logger
from lnbits.helpers import normalize_endpoint from lnbits.helpers import normalize_endpoint
@@ -81,11 +79,6 @@ class SparkL2Wallet(Wallet):
async def status(self) -> StatusResponse: async def status(self) -> StatusResponse:
try: try:
res = await self._request("POST", "/v1/balance") res = await self._request("POST", "/v1/balance")
status = res.get("status")
if status == "missing_mnemonic":
await self._check_sidecar_mnemonic()
return StatusResponse("Spark sidecar mnemonic not set", 0)
balance_msat = res.get("balance_msat") balance_msat = res.get("balance_msat")
if balance_msat is not None: if balance_msat is not None:
return StatusResponse(None, int(balance_msat)) return StatusResponse(None, int(balance_msat))
@@ -244,7 +237,7 @@ class SparkL2Wallet(Wallet):
) -> dict[str, Any]: ) -> dict[str, Any]:
error_message = None error_message = None
try: try:
r = await self.client.request(method, path, json=json_data, timeout=30) r = await self.client.request(method, path, json=json_data)
r.raise_for_status() r.raise_for_status()
j = r.json() j = r.json()
except (httpx.RequestError, httpx.HTTPStatusError, json.JSONDecodeError) as exc: except (httpx.RequestError, httpx.HTTPStatusError, json.JSONDecodeError) as exc:
@@ -326,30 +319,3 @@ class SparkL2Wallet(Wallet):
if mapped.failed: if mapped.failed:
return False return False
return None return None
async def _check_sidecar_mnemonic(self):
if settings.spark_l2_mnemonic:
valid = mnemonic_is_valid(settings.spark_l2_mnemonic)
if not valid:
logger.warning("SPARK_L2_MNEMONIC is set but invalid. Please recheck!")
return
await self._set_sidecar_mnemonic(settings.spark_l2_mnemonic)
return
logger.info("SPARK_L2_MNEMONIC is not set, one will be generated for you.")
mnemonic = mnemonic_from_bytes(PrivateKey().secret)
await self._set_sidecar_mnemonic(mnemonic)
async def _set_sidecar_mnemonic(self, mnemonic: str):
logger.info("Checking 'SPARK_L2_MNEMONIC' on the Spark sidecar.")
payload = {"mnemonic": mnemonic}
resp = await self._request("POST", "/v1/mnemonic", payload)
status = resp.get("status")
logger.info(f"Spark sidecar mnemonic status: {status}")
if status == "set":
logger.info("Updating 'SPARK_L2_MNEMONIC' mnemonic settings.")
from lnbits.core.crud.settings import set_settings_field
await set_settings_field("spark_l2_mnemonic", mnemonic)
else:
logger.info("Nothing to do for 'SPARK_L2_MNEMONIC' on the Spark sidecar.")
+3 -3
View File
@@ -1386,9 +1386,9 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.5", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "lnbits" name = "lnbits"
version = "1.5.1" version = "1.5.0-rc2"
requires-python = ">=3.10,<3.13" requires-python = ">=3.10,<3.13"
description = "LNbits, free and open-source Lightning wallet and accounts system." description = "LNbits, free and open-source Lightning wallet and accounts system."
authors = [{ name = "Alan Bits", email = "alan@lnbits.com" }] authors = [{ name = "Alan Bits", email = "alan@lnbits.com" }]
Generated
+4 -4
View File
@@ -1247,7 +1247,7 @@ wheels = [
[[package]] [[package]]
name = "lnbits" name = "lnbits"
version = "1.5.1" version = "1.5.0rc2"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "aiosqlite" }, { name = "aiosqlite" },
@@ -2769,14 +2769,14 @@ wheels = [
[[package]] [[package]]
name = "werkzeug" name = "werkzeug"
version = "3.1.6" version = "3.1.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "markupsafe" }, { name = "markupsafe" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/61/f1/ee81806690a87dab5f5653c1f146c92bc066d7f4cebc603ef88eb9e13957/werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25", size = 864736, upload-time = "2026-02-19T15:17:18.884Z" } sdist = { url = "https://files.pythonhosted.org/packages/5a/70/1469ef1d3542ae7c2c7b72bd5e3a4e6ee69d7978fa8a3af05a38eca5becf/werkzeug-3.1.5.tar.gz", hash = "sha256:6a548b0e88955dd07ccb25539d7d0cc97417ee9e179677d22c7041c8f078ce67", size = 864754, upload-time = "2026-01-08T17:49:23.247Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/4d/ec/d58832f89ede95652fd01f4f24236af7d32b70cab2196dfcc2d2fd13c5c2/werkzeug-3.1.6-py3-none-any.whl", hash = "sha256:7ddf3357bb9564e407607f988f683d72038551200c704012bb9a4c523d42f131", size = 225166, upload-time = "2026-02-19T15:17:17.475Z" }, { url = "https://files.pythonhosted.org/packages/ad/e4/8d97cca767bcc1be76d16fb76951608305561c6e056811587f36cb1316a8/werkzeug-3.1.5-py3-none-any.whl", hash = "sha256:5111e36e91086ece91f93268bb39b4a35c1e6f1feac762c9c822ded0a4e322dc", size = 225025, upload-time = "2026-01-08T17:49:21.859Z" },
] ]
[[package]] [[package]]