mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-03-15 12:20:21 +01: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
3 changed files with 135 additions and 6 deletions
|
@ -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]:
|
||||
|
|
|
@ -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"]}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue