feat: adds a wallet select to picking wallet + uv (#37)

* Adds a wallet select to picking wallet

* added uv

* uv uv uv

---------

Co-authored-by: dni  <office@dnilabs.com>
This commit is contained in:
Arc 2026-05-05 22:53:59 +01:00 committed by GitHub
commit 81184a0a53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 2364 additions and 3699 deletions

View file

@ -5,27 +5,27 @@ format: prettier black ruff
check: mypy pyright checkblack checkruff checkprettier check: mypy pyright checkblack checkruff checkprettier
prettier: prettier:
poetry run ./node_modules/.bin/prettier --write . uv run ./node_modules/.bin/prettier --write .
pyright: pyright:
poetry run ./node_modules/.bin/pyright uv run ./node_modules/.bin/pyright
mypy: mypy:
poetry run mypy . uv run mypy .
black: black:
poetry run black . uv run black .
ruff: ruff:
poetry run ruff check . --fix uv run ruff check . --fix
checkruff: checkruff:
poetry run ruff check . uv run ruff check .
checkprettier: checkprettier:
poetry run ./node_modules/.bin/prettier --check . uv run ./node_modules/.bin/prettier --check .
checkblack: checkblack:
poetry run black --check . uv run black --check .
checkeditorconfig: checkeditorconfig:
editorconfig-checker editorconfig-checker
@ -33,14 +33,14 @@ checkeditorconfig:
test: test:
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
DEBUG=true \ DEBUG=true \
poetry run pytest uv run pytest
install-pre-commit-hook: install-pre-commit-hook:
@echo "Installing pre-commit hook to git" @echo "Installing pre-commit hook to git"
@echo "Uninstall the hook with poetry run pre-commit uninstall" @echo "Uninstall the hook with uv run pre-commit uninstall"
poetry run pre-commit install uv run pre-commit install
pre-commit: pre-commit:
poetry run pre-commit run --all-files uv run pre-commit run --all-files
checkbundle: checkbundle:

View file

@ -41,7 +41,7 @@ def splitpayments_start():
__all__ = [ __all__ = [
"db", "db",
"splitpayments_ext", "splitpayments_ext",
"splitpayments_static_files",
"splitpayments_start", "splitpayments_start",
"splitpayments_static_files",
"splitpayments_stop", "splitpayments_stop",
] ]

View file

@ -1,5 +1,3 @@
from typing import Optional
from fastapi import Query from fastapi import Query
from pydantic import BaseModel from pydantic import BaseModel
@ -9,7 +7,7 @@ class Target(BaseModel):
wallet: str wallet: str
source: str source: str
percent: float percent: float
alias: Optional[str] = None alias: str | None = None
class TargetPut(BaseModel): class TargetPut(BaseModel):

3642
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,29 +1,30 @@
[project]
name = "splitpayments"
version = "1.1.1"
requires-python = ">=3.10,<3.13"
description = "Send incoming payments to different targets"
authors = [{name = "benarc"}, {name = "dni"}, {name = "alan"}]
urls = { Homepage = "https://lnbits.com", Repository = "https://github.com/lnbits/splitpayments" }
dependencies = [ "lnbits>1" ]
[tool.poetry] [tool.poetry]
name = "lnbits-splitpayments"
version = "0.0.0"
description = "LNbits, free and open-source Lightning wallet and accounts system."
authors = ["Alan Bits <alan@lnbits.com>"]
package-mode = false package-mode = false
[tool.poetry.dependencies] [tool.uv]
python = "~3.12 | ~3.11 | ~3.10" dev-dependencies = [
lnbits = {version = "*", allow-prereleases = true} "black",
"pytest-asyncio",
[tool.poetry.group.dev.dependencies] "pytest",
black = "^24.3.0" "mypy==1.17.1",
pytest-asyncio = "^0.21.0" "pre-commit",
pytest = "^7.3.2" "ruff",
mypy = "^1.17.1" "pytest-md",
pre-commit = "^3.2.2" ]
ruff = "^0.3.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.mypy] [tool.mypy]
exclude = "(nostr/*)" exclude = "(nostr/*)"
plugins = "pydantic.mypy" plugins = ["pydantic.mypy"]
[tool.pydantic-mypy] [tool.pydantic-mypy]
init_forbid_extra = true init_forbid_extra = true
@ -31,19 +32,6 @@ init_typed = true
warn_required_dynamic_aliases = true warn_required_dynamic_aliases = true
warn_untyped_fields = true warn_untyped_fields = true
[[tool.mypy.overrides]]
module = [
"lnbits.*",
"lnurl.*",
"loguru.*",
"fastapi.*",
"pydantic.*",
"pyqrcode.*",
"shortuuid.*",
"httpx.*",
]
ignore_missing_imports = "True"
[tool.pytest.ini_options] [tool.pytest.ini_options]
log_cli = false log_cli = false
testpaths = [ testpaths = [
@ -85,6 +73,7 @@ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
# needed for pydantic # needed for pydantic
[tool.ruff.lint.pep8-naming] [tool.ruff.lint.pep8-naming]
classmethod-decorators = [ classmethod-decorators = [
"validator",
"root_validator", "root_validator",
] ]

View file

@ -51,8 +51,11 @@ window.app = Vue.createApp({
'/splitpayments/api/v1/targets', '/splitpayments/api/v1/targets',
this.selectedWallet.adminkey this.selectedWallet.adminkey
) )
.then(response => { .then(res => {
this.targets = response.data this.targets = res.data.map(t => ({
...t,
targetChoice: t.targetChoice || 'wallet'
}))
}) })
.catch(err => { .catch(err => {
LNbits.utils.notifyApiError(err) LNbits.utils.notifyApiError(err)
@ -63,16 +66,26 @@ window.app = Vue.createApp({
this.getTargets() this.getTargets()
}, },
addTarget() { addTarget() {
this.targets.push({source: this.selectedWallet}) this.targets.push({
source: this.selectedWallet,
targetChoice: 'wallet'
})
}, },
saveTargets() { saveTargets() {
const payload = this.targets
.filter(t => t.wallet && String(t.wallet).trim() !== '')
.map(({alias, percent, wallet}) => ({
alias,
percent: Number(percent) || 0,
wallet
}))
LNbits.api LNbits.api
.request( .request(
'PUT', 'PUT',
'/splitpayments/api/v1/targets', '/splitpayments/api/v1/targets',
this.selectedWallet.adminkey, this.selectedWallet.adminkey,
{ {
targets: this.targets targets: payload
} }
) )
.then(response => { .then(response => {

View file

@ -1,6 +1,5 @@
import asyncio import asyncio
from math import floor from math import floor
from typing import Optional
import bolt11 import bolt11
from lnbits.core.crud import get_standalone_payment from lnbits.core.crud import get_standalone_payment
@ -100,7 +99,7 @@ async def pay_invoice_in_background(payment_request, wallet_id, description, ext
async def get_lnurl_invoice( async def get_lnurl_invoice(
payoraddress: str, wallet_id: str, amount_msat: int, memo: str payoraddress: str, wallet_id: str, amount_msat: int, memo: str
) -> Optional[str]: ) -> str | None:
rounded_amount = floor(amount_msat / 1000) * 1000 rounded_amount = floor(amount_msat / 1000) * 1000

View file

@ -38,12 +38,30 @@
:hint="t === targets.length - 1 ? 'A name to identify this target wallet locally.' : undefined" :hint="t === targets.length - 1 ? 'A name to identify this target wallet locally.' : undefined"
style="width: 150px" style="width: 150px"
></q-input> ></q-input>
<div class="column q-mt-none">
<div class="col">
<q-radio
class="float-left"
v-model="target.targetChoice"
val="wallet"
label="wallet"
></q-radio>
</div>
<div class="col">
<q-radio
class="float-left"
v-model="target.targetChoice"
val="lnurl"
label="lnurl"
></q-radio>
</div>
</div>
<q-input <q-input
v-if="target.targetChoice === 'lnurl'"
dense dense
v-model.trim="target.wallet" v-model.trim="target.wallet"
label="Target" label="Target"
hint="A wallet ID, invoice key, LNURLp or Lightning Address." hint="LNURLp or Lightning Address."
option-label="name" option-label="name"
style="width: 500px" style="width: 500px"
new-value-mode="add-unique" new-value-mode="add-unique"
@ -51,6 +69,19 @@
input-debounce="0" input-debounce="0"
emit-value emit-value
></q-input> ></q-input>
<q-select
v-if="target.targetChoice === 'wallet'"
class="q-pr-md q-pt-sm"
filled
dense
style="width: 500px"
v-model="target.wallet"
:options="g.user.walletOptions"
emit-value
map-options
label="Receive wallet *"
>
</q-select>
<q-input <q-input
style="width: 150px" style="width: 150px"

2277
uv.lock generated Normal file

File diff suppressed because it is too large Load diff