[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:
callebtc 2023-07-24 12:00:41 +02:00 committed by GitHub
parent f478c1848a
commit 11fec7a889
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 135 additions and 6 deletions

View file

@ -161,15 +161,18 @@ class CoreLightningWallet(Wallet):
return PaymentStatus(True)
elif invoice_resp["status"] == "unpaid":
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)
async def get_payment_status(self, checking_id: str) -> PaymentStatus:
try:
r = self.ln.call("listpays", {"payment_hash": checking_id})
r = self.ln.listpays(payment_hash=checking_id)
except:
return PaymentStatus(None)
if not r["pays"]:
if "pays" not in r or not r["pays"]:
return PaymentStatus(None)
payment_resp = r["pays"][-1]
@ -183,8 +186,10 @@ class CoreLightningWallet(Wallet):
return PaymentStatus(True, fee_msat, payment_resp["preimage"])
elif status == "failed":
return PaymentStatus(False)
return PaymentStatus(None)
logger.warning(f"supplied an invalid checking_id: {checking_id}")
else:
return PaymentStatus(None)
else:
logger.warning(f"supplied an invalid checking_id: {checking_id}")
return PaymentStatus(None)
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:

View file

@ -125,7 +125,7 @@ async def invoice(to_wallet):
del invoice
@pytest_asyncio.fixture(scope="session")
@pytest_asyncio.fixture(scope="function")
async def real_invoice():
invoice = get_real_invoice(100)
yield {"bolt11": invoice["payment_request"]}

View file

@ -5,6 +5,7 @@ from time import time
import pytest
from lnbits import bolt11
from lnbits.core.crud import get_standalone_payment, update_payment_details
from lnbits.core.models import Payment
from lnbits.core.views.admin_api import api_auditor
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)
balance = await get_node_balance_sats()
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