mirror of
https://github.com/lnbits/lnbits.git
synced 2025-05-06 01:30:18 +02:00
[Wallets] CLN: fix pending state check (#1770)
* better checking * flake8 fix * make format * invoices scope are function for tests * invoice back to sessionbut keep real_invoice for now * make format * comment * get payment by checking id and test
This commit is contained in:
parent
f478c1848a
commit
11fec7a889
@ -161,15 +161,18 @@ class CoreLightningWallet(Wallet):
|
|||||||
return PaymentStatus(True)
|
return PaymentStatus(True)
|
||||||
elif invoice_resp["status"] == "unpaid":
|
elif invoice_resp["status"] == "unpaid":
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
logger.warning(f"supplied an invalid checking_id: {checking_id}")
|
elif invoice_resp["status"] == "expired":
|
||||||
|
return PaymentStatus(False)
|
||||||
|
else:
|
||||||
|
logger.warning(f"supplied an invalid checking_id: {checking_id}")
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
||||||
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
|
||||||
try:
|
try:
|
||||||
r = self.ln.call("listpays", {"payment_hash": checking_id})
|
r = self.ln.listpays(payment_hash=checking_id)
|
||||||
except:
|
except:
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
if not r["pays"]:
|
if "pays" not in r or not r["pays"]:
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
payment_resp = r["pays"][-1]
|
payment_resp = r["pays"][-1]
|
||||||
|
|
||||||
@ -183,8 +186,10 @@ class CoreLightningWallet(Wallet):
|
|||||||
return PaymentStatus(True, fee_msat, payment_resp["preimage"])
|
return PaymentStatus(True, fee_msat, payment_resp["preimage"])
|
||||||
elif status == "failed":
|
elif status == "failed":
|
||||||
return PaymentStatus(False)
|
return PaymentStatus(False)
|
||||||
return PaymentStatus(None)
|
else:
|
||||||
logger.warning(f"supplied an invalid checking_id: {checking_id}")
|
return PaymentStatus(None)
|
||||||
|
else:
|
||||||
|
logger.warning(f"supplied an invalid checking_id: {checking_id}")
|
||||||
return PaymentStatus(None)
|
return PaymentStatus(None)
|
||||||
|
|
||||||
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
|
||||||
|
@ -125,7 +125,7 @@ async def invoice(to_wallet):
|
|||||||
del invoice
|
del invoice
|
||||||
|
|
||||||
|
|
||||||
@pytest_asyncio.fixture(scope="session")
|
@pytest_asyncio.fixture(scope="function")
|
||||||
async def real_invoice():
|
async def real_invoice():
|
||||||
invoice = get_real_invoice(100)
|
invoice = get_real_invoice(100)
|
||||||
yield {"bolt11": invoice["payment_request"]}
|
yield {"bolt11": invoice["payment_request"]}
|
||||||
|
@ -5,6 +5,7 @@ from time import time
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from lnbits import bolt11
|
from lnbits import bolt11
|
||||||
|
from lnbits.core.crud import get_standalone_payment, update_payment_details
|
||||||
from lnbits.core.models import Payment
|
from lnbits.core.models import Payment
|
||||||
from lnbits.core.views.admin_api import api_auditor
|
from lnbits.core.views.admin_api import api_auditor
|
||||||
from lnbits.core.views.api import api_payment
|
from lnbits.core.views.api import api_payment
|
||||||
@ -387,3 +388,126 @@ async def test_create_real_invoice(client, adminkey_headers_from, inkey_headers_
|
|||||||
await asyncio.sleep(0.3)
|
await asyncio.sleep(0.3)
|
||||||
balance = await get_node_balance_sats()
|
balance = await get_node_balance_sats()
|
||||||
assert balance - prev_balance == create_invoice.amount
|
assert balance - prev_balance == create_invoice.amount
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skipif(is_fake, reason="this only works in regtest")
|
||||||
|
async def test_pay_real_invoice_set_pending_and_check_state(
|
||||||
|
client, real_invoice, adminkey_headers_from, inkey_headers_from
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
1. We create an invoice
|
||||||
|
2. We pay it
|
||||||
|
3. We verify that the inoice was paid
|
||||||
|
4. We set the invoice to pending in the database
|
||||||
|
5. We recheck the state of the invoice
|
||||||
|
6. We verify that the invoice is paid
|
||||||
|
"""
|
||||||
|
response = await client.post(
|
||||||
|
"/api/v1/payments", json=real_invoice, headers=adminkey_headers_from
|
||||||
|
)
|
||||||
|
assert response.status_code < 300
|
||||||
|
invoice = response.json()
|
||||||
|
assert len(invoice["payment_hash"]) == 64
|
||||||
|
assert len(invoice["checking_id"]) > 0
|
||||||
|
|
||||||
|
# check the payment status
|
||||||
|
response = await api_payment(
|
||||||
|
invoice["payment_hash"], inkey_headers_from["X-Api-Key"]
|
||||||
|
)
|
||||||
|
assert response["paid"]
|
||||||
|
|
||||||
|
status = await WALLET.get_payment_status(invoice["payment_hash"])
|
||||||
|
assert status.paid
|
||||||
|
|
||||||
|
# get the outgoing payment from the db
|
||||||
|
payment = await get_standalone_payment(invoice["payment_hash"])
|
||||||
|
assert payment
|
||||||
|
assert payment.pending is False
|
||||||
|
|
||||||
|
# set the outgoing invoice to pending
|
||||||
|
await update_payment_details(payment.checking_id, pending=True)
|
||||||
|
|
||||||
|
payment_pending = await get_standalone_payment(invoice["payment_hash"])
|
||||||
|
assert payment_pending
|
||||||
|
assert payment_pending.pending is True
|
||||||
|
|
||||||
|
# check the outgoing payment status
|
||||||
|
await payment.check_status()
|
||||||
|
|
||||||
|
payment_not_pending = await get_standalone_payment(invoice["payment_hash"])
|
||||||
|
assert payment_not_pending
|
||||||
|
assert payment_not_pending.pending is False
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
@pytest.mark.skipif(is_fake, reason="this only works in regtest")
|
||||||
|
async def test_receive_real_invoice_set_pending_and_check_state(
|
||||||
|
client, adminkey_headers_from, inkey_headers_from
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
1. We create a real invoice
|
||||||
|
2. We pay it from our wallet
|
||||||
|
3. We check that the inoice was paid with the backend
|
||||||
|
4. We set the invoice to pending in the database
|
||||||
|
5. We recheck the state of the invoice with the backend
|
||||||
|
6. We verify that the invoice is now marked as paid in the database
|
||||||
|
"""
|
||||||
|
create_invoice = CreateInvoiceData(out=False, amount=1000, memo="test")
|
||||||
|
response = await client.post(
|
||||||
|
"/api/v1/payments",
|
||||||
|
json=create_invoice.dict(),
|
||||||
|
headers=adminkey_headers_from,
|
||||||
|
)
|
||||||
|
assert response.status_code < 300
|
||||||
|
invoice = response.json()
|
||||||
|
response = await api_payment(
|
||||||
|
invoice["payment_hash"], inkey_headers_from["X-Api-Key"]
|
||||||
|
)
|
||||||
|
assert not response["paid"]
|
||||||
|
|
||||||
|
async def listen():
|
||||||
|
async for payment_hash in get_wallet_class().paid_invoices_stream():
|
||||||
|
assert payment_hash == invoice["payment_hash"]
|
||||||
|
return
|
||||||
|
|
||||||
|
task = asyncio.create_task(listen())
|
||||||
|
pay_real_invoice(invoice["payment_request"])
|
||||||
|
await asyncio.wait_for(task, timeout=3)
|
||||||
|
response = await api_payment(
|
||||||
|
invoice["payment_hash"], inkey_headers_from["X-Api-Key"]
|
||||||
|
)
|
||||||
|
assert response["paid"]
|
||||||
|
|
||||||
|
# get the incoming payment from the db
|
||||||
|
payment = await get_standalone_payment(invoice["payment_hash"], incoming=True)
|
||||||
|
assert payment
|
||||||
|
assert payment.pending is False
|
||||||
|
|
||||||
|
# set the incoming invoice to pending
|
||||||
|
await update_payment_details(payment.checking_id, pending=True)
|
||||||
|
|
||||||
|
payment_pending = await get_standalone_payment(
|
||||||
|
invoice["payment_hash"], incoming=True
|
||||||
|
)
|
||||||
|
assert payment_pending
|
||||||
|
assert payment_pending.pending is True
|
||||||
|
|
||||||
|
# check the incoming payment status
|
||||||
|
await payment.check_status()
|
||||||
|
|
||||||
|
payment_not_pending = await get_standalone_payment(
|
||||||
|
invoice["payment_hash"], incoming=True
|
||||||
|
)
|
||||||
|
assert payment_not_pending
|
||||||
|
assert payment_not_pending.pending is False
|
||||||
|
|
||||||
|
# verify we get the same result if we use the checking_id to look up the payment
|
||||||
|
payment_by_checking_id = await get_standalone_payment(
|
||||||
|
payment_not_pending.checking_id, incoming=True
|
||||||
|
)
|
||||||
|
|
||||||
|
assert payment_by_checking_id
|
||||||
|
assert payment_by_checking_id.pending is False
|
||||||
|
assert payment_by_checking_id.bolt11 == payment_not_pending.bolt11
|
||||||
|
assert payment_by_checking_id.payment_hash == payment_not_pending.payment_hash
|
||||||
|
Loading…
x
Reference in New Issue
Block a user