Compare commits

..

No commits in common. "main" and "v1.1.0" have entirely different histories.

11 changed files with 3703 additions and 2368 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:
uv run ./node_modules/.bin/prettier --write . poetry run ./node_modules/.bin/prettier --write .
pyright: pyright:
uv run ./node_modules/.bin/pyright poetry run ./node_modules/.bin/pyright
mypy: mypy:
uv run mypy . poetry run mypy .
black: black:
uv run black . poetry run black .
ruff: ruff:
uv run ruff check . --fix poetry run ruff check . --fix
checkruff: checkruff:
uv run ruff check . poetry run ruff check .
checkprettier: checkprettier:
uv run ./node_modules/.bin/prettier --check . poetry run ./node_modules/.bin/prettier --check .
checkblack: checkblack:
uv run black --check . poetry run black --check .
checkeditorconfig: checkeditorconfig:
editorconfig-checker editorconfig-checker
@ -33,14 +33,14 @@ checkeditorconfig:
test: test:
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
DEBUG=true \ DEBUG=true \
uv run pytest poetry 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 uv run pre-commit uninstall" @echo "Uninstall the hook with poetry run pre-commit uninstall"
uv run pre-commit install poetry run pre-commit install
pre-commit: pre-commit:
uv run pre-commit run --all-files poetry run pre-commit run --all-files
checkbundle: checkbundle:

View file

@ -33,9 +33,9 @@ LNbits Split Payments extension allows for distributing payments across multiple
IMPORTANT: IMPORTANT:
- If you split to a LNURLp or LNaddress through the LNURLp extension make sure your recipients allow comments ! Split&Scrub add a comment in your transaction - and if it is not allowed, the split/scrub will not take place. - If you split to a LNURLp or LNaddress through the LNURLp extension make sure your receipients allow comments ! Split&Scrub add a comment in your transaction - and if it is not allowed, the split/scrub will not take place.
- Make sure the LNURLp / LNaddress of the recipient has its min-sats set very low (e.g. 1 sat). If the wallet does not belong to you you can [check with a Decoder](https://lightningdecoder.com/), if that is the case already - Make sure the LNURLp / LNaddress of the receipient has its min-sats set very low (e.g. 1 sat). If the wallet does not belong to you you can [check with a Decoder](https://lightningdecoder.com/), if that is the case already
- Yes, there is fees - internal and external! Updating your own wallets on your own instance will not cost any fees but sending to an external instance will. Please notice that you should therefore not split up to 100% if you send to a wallet that is external (leave 1-2% reserve for routing fees!). External fees are deducted from the individual payment percentage of the recipient - Yes, there is fees - internal and external! Updating your own wallets on your own instance will not cost any fees but sending to an external instance will. Please notice that you should therefore not split up to 100% if you send to a wallet that is external (leave 1-2% reserve for routing fees!). External fees are deducted from the individual payment percentage of the receipient
<img width="1148" alt="Bildschirm­foto 2023-05-01 um 22 14 36" src="https://user-images.githubusercontent.com/63317640/235534056-49296aeb-7295-4b4e-9f57-914a677f5ad4.png"> <img width="1148" alt="Bildschirm­foto 2023-05-01 um 22 14 36" src="https://user-images.githubusercontent.com/63317640/235534056-49296aeb-7295-4b4e-9f57-914a677f5ad4.png">
<img width="1402" alt="Bildschirm­foto 2023-05-01 um 22 17 52" src="https://user-images.githubusercontent.com/63317640/235534063-b2734654-7c1a-48a3-b48e-32798c232b49.png"> <img width="1402" alt="Bildschirm­foto 2023-05-01 um 22 17 52" src="https://user-images.githubusercontent.com/63317640/235534063-b2734654-7c1a-48a3-b48e-32798c232b49.png">

View file

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

View file

@ -2,7 +2,7 @@
"repos": [ "repos": [
{ {
"id": "splitpayments", "id": "splitpayments",
"organisation": "PatMulligan", "organisation": "lnbits",
"repository": "splitpayments" "repository": "splitpayments"
} }
] ]

View file

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

3642
poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,30 +1,29 @@
[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.uv] [tool.poetry.dependencies]
dev-dependencies = [ python = "~3.12 | ~3.11 | ~3.10"
"black", lnbits = {version = "*", allow-prereleases = true}
"pytest-asyncio",
"pytest", [tool.poetry.group.dev.dependencies]
"mypy==1.17.1", black = "^24.3.0"
"pre-commit", pytest-asyncio = "^0.21.0"
"ruff", pytest = "^7.3.2"
"pytest-md", mypy = "^1.17.1"
] 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
@ -32,6 +31,19 @@ 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 = [
@ -73,7 +85,6 @@ 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,11 +51,8 @@ window.app = Vue.createApp({
'/splitpayments/api/v1/targets', '/splitpayments/api/v1/targets',
this.selectedWallet.adminkey this.selectedWallet.adminkey
) )
.then(res => { .then(response => {
this.targets = res.data.map(t => ({ this.targets = response.data
...t,
targetChoice: t.targetChoice || 'wallet'
}))
}) })
.catch(err => { .catch(err => {
LNbits.utils.notifyApiError(err) LNbits.utils.notifyApiError(err)
@ -66,26 +63,16 @@ window.app = Vue.createApp({
this.getTargets() this.getTargets()
}, },
addTarget() { addTarget() {
this.targets.push({ this.targets.push({source: this.selectedWallet})
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: payload targets: this.targets
} }
) )
.then(response => { .then(response => {

View file

@ -1,5 +1,6 @@
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
@ -99,7 +100,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
) -> str | None: ) -> Optional[str]:
rounded_amount = floor(amount_msat / 1000) * 1000 rounded_amount = floor(amount_msat / 1000) * 1000

View file

@ -38,30 +38,12 @@
: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="LNURLp or Lightning Address." hint="A wallet ID, invoice key, 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"
@ -69,19 +51,6 @@
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

File diff suppressed because it is too large Load diff