Merge remote-tracking branch 'upstream/main' into fixhardn

This commit is contained in:
Riccardo Balbo 2025-06-25 16:28:34 +02:00
commit 18f04bcef0
4 changed files with 81 additions and 14 deletions

View file

@ -1,9 +1,7 @@
{ {
"name": "lnbits_nwc_provider", "name": "lnbits_nwc_provider",
"image": "mcr.microsoft.com/devcontainers/python:1-3.12", "image": "mcr.microsoft.com/devcontainers/python:1-3.12",
"features": {
"ghcr.io/devcontainers-contrib/features/poetry:2": {}
},
"mounts": [ "mounts": [
"source=${localWorkspaceFolder}/.devcontainer/start.sh,target=/start-lnbits.sh,type=bind", "source=${localWorkspaceFolder}/.devcontainer/start.sh,target=/start-lnbits.sh,type=bind",
"source=${localWorkspaceFolder}/.devcontainer/setup.sh,target=/setup.sh,type=bind", "source=${localWorkspaceFolder}/.devcontainer/setup.sh,target=/setup.sh,type=bind",

View file

@ -5,6 +5,7 @@ sudo apt update -y
sudo apt install -y curl sudo apt install -y curl
sudo apt-get install -y docker.io sudo apt-get install -y docker.io
curl -sSL https://install.python-poetry.org | python3 -
curl -fsSL https://deb.nodesource.com/setup_20.x -o /tmp/nodesource_setup.sh curl -fsSL https://deb.nodesource.com/setup_20.x -o /tmp/nodesource_setup.sh
sudo bash /tmp/nodesource_setup.sh sudo bash /tmp/nodesource_setup.sh
sudo apt-get install -y nodejs sudo apt-get install -y nodejs

View file

@ -375,16 +375,17 @@ async def _on_list_transactions(
return [(None, error, [])] return [(None, error, [])]
if not nwc: if not nwc:
raise Exception("Pubkey has no associated wallet") raise Exception("Pubkey has no associated wallet")
tfrom = payload.get("from", 0) params = payload.get("params", 0)
tto = payload.get("to", int(time.time())) tfrom = params.get("from", 0)
limit = payload.get("limit", 10) tuntil = params.get("until", int(time.time()))
offset = payload.get("offset", 0) limit = params.get("limit", 10)
unpaid = payload.get("unpaid", False) offset = params.get("offset", 0)
tx_type = payload.get("type", "") unpaid = params.get("unpaid", False)
tx_type = params.get("type", "")
# hardening # # hardening #
assert_valid_positive_int(tfrom) assert_valid_positive_int(tfrom)
assert_valid_positive_int(tto) assert_valid_positive_int(tuntil)
assert_valid_positive_int(limit) assert_valid_positive_int(limit)
assert_valid_positive_int(offset) assert_valid_positive_int(offset)
assert_boolean(unpaid) assert_boolean(unpaid)
@ -394,7 +395,7 @@ async def _on_list_transactions(
values = [] values = []
filters: Filters = Filters() filters: Filters = Filters()
filters.where(["time <= ?"]) filters.where(["time <= ?"])
values.append(tto) values.append(tuntil)
filters.values(values) filters.values(values)
history = await get_payments( history = await get_payments(
wallet_id=nwc.wallet, wallet_id=nwc.wallet,

View file

@ -183,7 +183,11 @@ class NWCWallet:
async def _wait_for_connection(self): async def _wait_for_connection(self):
while not self.connected: while not self.connected:
await asyncio.sleep(0.2) try:
await asyncio.sleep(0.2)
except asyncio.CancelledError:
logger.debug("Connection wait cancelled")
return
async def start(self): async def start(self):
self.task = asyncio.create_task(self._run()) self.task = asyncio.create_task(self._run())
@ -335,7 +339,7 @@ class NWCWallet:
await self.ws.send(self._json_dumps(["EVENT", event])) await self.ws.send(self._json_dumps(["EVENT", event]))
async def wait_for( async def wait_for(
self, result_type, callback=None, on_error_callback=None, timeout=60 self, result_type, callback=None, on_error_callback=None, timeout=60000
): ):
now = time.time() now = time.time()
while True: while True:
@ -627,6 +631,7 @@ async def test_multi_pay_invoices():
assert not error assert not error
assert result["invoice"] assert result["invoice"]
invoice3 = result["invoice"] invoice3 = result["invoice"]
invoice3_payhash = result["payment_hash"]
await wallet3.send_event( await wallet3.send_event(
"multi_pay_invoice", "multi_pay_invoice",
@ -645,7 +650,7 @@ async def test_multi_pay_invoices():
assert result["preimage"] assert result["preimage"]
elif d_tag == "invoice2": elif d_tag == "invoice2":
assert result["preimage"] assert result["preimage"]
elif d_tag == invoice3: elif d_tag == invoice3_payhash:
assert result["preimage"] assert result["preimage"]
else: else:
raise AssertionError("Unexpected d tag") raise AssertionError("Unexpected d tag")
@ -991,3 +996,65 @@ async def create_valid_invoice(wallet, amount=1000):
if error: if error:
raise Exception(f"Failed to create invoice: {error}") raise Exception(f"Failed to create invoice: {error}")
return result["invoice"] return result["invoice"]
@pytest.mark.asyncio
async def test_list_transactions():
# Create wallets with required permissions
nwc1 = await create_nwc(
"wallet1", "test_list_transactions", ["invoice", "pay", "balance", "history"], [], 0
)
nwc2 = await create_nwc(
"wallet2", "test_list_transactions", ["invoice", "pay", "balance", "history"], [], 0
)
wallet1 = NWCWallet(nwc1["pairing"])
wallet2 = NWCWallet(nwc2["pairing"])
try:
await wallet1.start()
await wallet2.start()
# First invoice
await wallet1.send_event(
"make_invoice", {"amount": 1000, "description": "test invoice 1"}
)
result1, _, error = await wallet1.wait_for("make_invoice")
assert not error
invoice1 = result1["invoice"]
# Pay first invoice
await wallet2.send_event("pay_invoice", {"invoice": invoice1})
_, _, error = await wallet2.wait_for("pay_invoice")
assert not error
# Second invoice
await wallet1.send_event(
"make_invoice", {"amount": 2000, "description": "test invoice 2"}
)
result2, _, error = await wallet1.wait_for("make_invoice")
assert not error
invoice2 = result2["invoice"]
# Pay second invoice
await wallet2.send_event("pay_invoice", {"invoice": invoice2})
_, _, error = await wallet2.wait_for("pay_invoice")
assert not error
# Test basic transaction listing
await wallet1.send_event("list_transactions", {})
result, _, error = await wallet1.wait_for("list_transactions")
assert not error
assert "transactions" in result
transactions = result["transactions"]
assert len(transactions) >= 2
# Test limit
await wallet1.send_event("list_transactions", {"limit": 1})
result, _, error = await wallet1.wait_for("list_transactions")
assert not error
limited_txs = result["transactions"]
assert len(limited_txs) == 1
finally:
await wallet1.close()
await wallet2.close()