mirror of
https://github.com/lnbits/lnbits.git
synced 2025-10-10 20:42:32 +02:00
test
add tests fix interface
This commit is contained in:
@@ -29,6 +29,7 @@ from lnbits.wallets.base import (
|
|||||||
PaymentResponse,
|
PaymentResponse,
|
||||||
PaymentStatus,
|
PaymentStatus,
|
||||||
PaymentSuccessStatus,
|
PaymentSuccessStatus,
|
||||||
|
UnsupportedError,
|
||||||
)
|
)
|
||||||
|
|
||||||
from ..crud import (
|
from ..crud import (
|
||||||
@@ -965,17 +966,15 @@ async def create_hold_invoice(
|
|||||||
invoice_memo = None if description_hash else memo
|
invoice_memo = None if description_hash else memo
|
||||||
|
|
||||||
funding_source = get_funding_source()
|
funding_source = get_funding_source()
|
||||||
if funding_source.__class__.__name__ not in ["LndRestWallet", "LndWallet"]:
|
try:
|
||||||
raise InvoiceError(
|
res = await funding_source.create_hold_invoice(
|
||||||
"Hold invoices are only supported with LND.", status="failed"
|
amount=amount,
|
||||||
|
memo=invoice_memo,
|
||||||
|
rhash=rhash,
|
||||||
|
description_hash=description_hash,
|
||||||
)
|
)
|
||||||
|
except UnsupportedError as exc:
|
||||||
res = await funding_source.create_hold_invoice(
|
raise InvoiceError(str(exc), status="failed") from exc
|
||||||
amount=amount,
|
|
||||||
memo=invoice_memo,
|
|
||||||
rhash=rhash,
|
|
||||||
description_hash=description_hash,
|
|
||||||
)
|
|
||||||
|
|
||||||
if not res.ok:
|
if not res.ok:
|
||||||
raise InvoiceError(
|
raise InvoiceError(
|
||||||
@@ -1004,23 +1003,24 @@ async def create_hold_invoice(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: should return payment
|
||||||
|
# TODO: update payment status to success
|
||||||
async def settle_hold_invoice(
|
async def settle_hold_invoice(
|
||||||
*,
|
*,
|
||||||
preimage: str,
|
preimage: str,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if len(preimage) != 32:
|
if len(bytes.fromhex(preimage)) != 32:
|
||||||
raise InvoiceError(
|
raise InvoiceError(
|
||||||
"Invalid preimage length. Must be 32 bytes",
|
"Invalid preimage length. Must be 32 bytes",
|
||||||
status="failed",
|
status="failed",
|
||||||
)
|
)
|
||||||
|
|
||||||
funding_source = get_funding_source()
|
funding_source = get_funding_source()
|
||||||
if funding_source.__class__.__name__ not in ["LndRestWallet", "LndWallet"]:
|
|
||||||
raise InvoiceError(
|
|
||||||
"Hold invoices are only supported with LND.", status="failed"
|
|
||||||
)
|
|
||||||
|
|
||||||
response = await funding_source.settle_hold_invoice(preimage=preimage)
|
try:
|
||||||
|
response = await funding_source.settle_hold_invoice(preimage=preimage)
|
||||||
|
except UnsupportedError as exc:
|
||||||
|
raise InvoiceError(str(exc), status="failed") from exc
|
||||||
|
|
||||||
if not response.ok:
|
if not response.ok:
|
||||||
raise InvoiceError("Unexpected backend error.", status="failed")
|
raise InvoiceError("Unexpected backend error.", status="failed")
|
||||||
@@ -1028,32 +1028,38 @@ async def settle_hold_invoice(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def cancel_hold_invoice(payment_hash: str) -> bool:
|
async def cancel_hold_invoice(payment_hash: str) -> Payment:
|
||||||
|
payment = await get_standalone_payment(payment_hash, incoming=True)
|
||||||
|
if not payment:
|
||||||
|
raise InvoiceError("Payment not found.", status="failed")
|
||||||
|
|
||||||
funding_source = get_funding_source()
|
funding_source = get_funding_source()
|
||||||
if funding_source.__class__.__name__ not in ["LndRestWallet", "LndWallet"]:
|
try:
|
||||||
raise InvoiceError(
|
response = await funding_source.cancel_hold_invoice(payment_hash=payment_hash)
|
||||||
"Hold invoices are only supported with LND.", status="failed"
|
except UnsupportedError as exc:
|
||||||
)
|
raise InvoiceError(str(exc), status="failed") from exc
|
||||||
response = await funding_source.cancel_hold_invoice(payment_hash=payment_hash)
|
|
||||||
if not response.ok:
|
if not response.ok:
|
||||||
raise InvoiceError("Unexpected backend error.", status="failed")
|
raise InvoiceError(
|
||||||
|
response.error_message or "Unexpected backend error.", status="failed"
|
||||||
return True
|
)
|
||||||
|
payment.status = PaymentState.FAILED
|
||||||
|
await update_payment(payment)
|
||||||
|
return payment
|
||||||
|
|
||||||
|
|
||||||
async def subscribe_hold_invoice(payment_hash: str) -> bool:
|
async def subscribe_hold_invoice(payment_hash: str) -> bool:
|
||||||
payment = await get_standalone_payment(payment_hash, incoming=True)
|
payment = await get_standalone_payment(payment_hash, incoming=True)
|
||||||
if not payment:
|
if not payment:
|
||||||
raise InvoiceError("Payment not found.", status="failed")
|
raise InvoiceError("Payment not found.", status="failed")
|
||||||
funding_source = get_funding_source()
|
# funding_source = get_funding_source()
|
||||||
if funding_source.__class__.__name__ not in ["LndRestWallet", "LndWallet"]:
|
try:
|
||||||
raise InvoiceError(
|
# if payment.webhook:
|
||||||
"Hold invoices are only supported with LND.", status="failed"
|
# asyncio. create_task(
|
||||||
)
|
# funding_source.hold_invoices_stream(
|
||||||
# if payment.webhook:
|
# payment_hash=payment_hash, webhook=payment.webhook
|
||||||
# asyncio. create_task(
|
# )
|
||||||
# funding_source.hold_invoices_stream(
|
# )
|
||||||
# payment_hash=payment_hash, webhook=payment.webhook
|
pass
|
||||||
# )
|
except UnsupportedError as exc:
|
||||||
# )
|
raise InvoiceError(str(exc), status="failed") from exc
|
||||||
return True
|
return True
|
||||||
|
@@ -346,9 +346,12 @@ class LndRestWallet(Wallet):
|
|||||||
else:
|
else:
|
||||||
data["memo"] = memo or ""
|
data["memo"] = memo or ""
|
||||||
|
|
||||||
r = await self.client.post(url="/v2/invoices/hodl", json=data)
|
try:
|
||||||
r.raise_for_status()
|
r = await self.client.post(url="/v2/invoices/hodl", json=data)
|
||||||
data = r.json()
|
r.raise_for_status()
|
||||||
|
data = r.json()
|
||||||
|
except httpx.HTTPStatusError as exc:
|
||||||
|
return InvoiceResponse(False, None, None, exc.response.text)
|
||||||
|
|
||||||
payment_request = data["payment_request"]
|
payment_request = data["payment_request"]
|
||||||
payment_hash = base64.b64encode(bytes.fromhex(rhash)).decode("ascii")
|
payment_hash = base64.b64encode(bytes.fromhex(rhash)).decode("ascii")
|
||||||
@@ -357,20 +360,27 @@ class LndRestWallet(Wallet):
|
|||||||
return InvoiceResponse(True, checking_id, payment_request, None)
|
return InvoiceResponse(True, checking_id, payment_request, None)
|
||||||
|
|
||||||
async def settle_hold_invoice(self, preimage: str) -> PaymentResponse:
|
async def settle_hold_invoice(self, preimage: str) -> PaymentResponse:
|
||||||
data: dict = {"preimage": base64.b64encode(preimage.encode()).decode("ascii")}
|
data: dict = {
|
||||||
r = await self.client.post(url="/v2/invoices/settle", json=data)
|
"preimage": base64.b64encode(bytes.fromhex(preimage)).decode("ascii")
|
||||||
r.raise_for_status()
|
}
|
||||||
|
try:
|
||||||
return PaymentResponse(True, None, None, None, None)
|
r = await self.client.post(url="/v2/invoices/settle", json=data)
|
||||||
|
r.raise_for_status()
|
||||||
|
return PaymentResponse(True, None, None, None, None)
|
||||||
|
except httpx.HTTPStatusError as exc:
|
||||||
|
return PaymentResponse(False, None, None, None, exc.response.text)
|
||||||
|
|
||||||
async def cancel_hold_invoice(self, payment_hash: str) -> PaymentResponse:
|
async def cancel_hold_invoice(self, payment_hash: str) -> PaymentResponse:
|
||||||
data: dict = {
|
rhash = bytes.fromhex(payment_hash)
|
||||||
"payment_hash": base64.b64encode(payment_hash.encode()).decode("ascii")
|
try:
|
||||||
}
|
r = await self.client.post(
|
||||||
r = await self.client.post(url="/v2/invoices/cancel", json=data)
|
url="/v2/invoices/cancel",
|
||||||
r.raise_for_status()
|
json={"payment_hash": base64.b64encode(rhash).decode("ascii")},
|
||||||
|
)
|
||||||
return PaymentResponse(True, None, None, None, None)
|
r.raise_for_status()
|
||||||
|
return PaymentResponse(True, None, None, None, None)
|
||||||
|
except httpx.HTTPStatusError as exc:
|
||||||
|
return PaymentResponse(False, None, None, None, exc.response.text)
|
||||||
|
|
||||||
async def hold_invoices_stream(self, payment_hash: str, webhook: str):
|
async def hold_invoices_stream(self, payment_hash: str, webhook: str):
|
||||||
try:
|
try:
|
||||||
|
59
tests/regtest/test_real_hold_invoice.py
Normal file
59
tests/regtest/test_real_hold_invoice.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from lnbits.core.services.payments import (
|
||||||
|
cancel_hold_invoice,
|
||||||
|
create_hold_invoice,
|
||||||
|
settle_hold_invoice,
|
||||||
|
)
|
||||||
|
from lnbits.exceptions import InvoiceError
|
||||||
|
|
||||||
|
from ..helpers import funding_source, is_fake
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.anyio
|
||||||
|
@pytest.mark.skipif(is_fake, reason="this only works in regtest")
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
funding_source.__class__.__name__ in ["LndRestWallet", "LndWallet"],
|
||||||
|
reason="this should not raise for lnd",
|
||||||
|
)
|
||||||
|
async def test_pay_raise_unsupported():
|
||||||
|
rhash = "0" * 32
|
||||||
|
with pytest.raises(InvoiceError):
|
||||||
|
await create_hold_invoice(
|
||||||
|
wallet_id="fake_wallet_id",
|
||||||
|
amount=1000,
|
||||||
|
memo="fake_holdinvoice",
|
||||||
|
rhash=rhash,
|
||||||
|
)
|
||||||
|
with pytest.raises(InvoiceError):
|
||||||
|
await settle_hold_invoice(preimage=rhash)
|
||||||
|
with pytest.raises(InvoiceError):
|
||||||
|
await cancel_hold_invoice(rhash)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.anyio
|
||||||
|
@pytest.mark.skipif(is_fake, reason="this only works in regtest")
|
||||||
|
@pytest.mark.skipif(
|
||||||
|
funding_source.__class__.__name__ not in ["LndRestWallet"],
|
||||||
|
reason="this only works for lndrest",
|
||||||
|
)
|
||||||
|
async def test_pay_real_hold_invoice(from_wallet):
|
||||||
|
|
||||||
|
preimage = os.urandom(32)
|
||||||
|
preimage_hash = hashlib.sha256(preimage).hexdigest()
|
||||||
|
payment = await create_hold_invoice(
|
||||||
|
wallet_id=from_wallet.id,
|
||||||
|
amount=1000,
|
||||||
|
memo="test_holdinvoice",
|
||||||
|
rhash=preimage_hash,
|
||||||
|
)
|
||||||
|
assert payment.amount == 1000 * 1000
|
||||||
|
assert payment.memo == "test_holdinvoice"
|
||||||
|
assert payment.status == "pending"
|
||||||
|
assert payment.wallet_id == from_wallet.id
|
||||||
|
|
||||||
|
payment = await cancel_hold_invoice(payment_hash=preimage_hash)
|
||||||
|
assert payment.status == "failed"
|
Reference in New Issue
Block a user