fix: guard internal payments

This commit is contained in:
Vlad Stan 2025-05-13 10:03:54 +03:00
parent 205190682b
commit 4eb8ca5ac6
2 changed files with 17 additions and 4 deletions

View File

@ -46,6 +46,8 @@ from .notifications import send_payment_notification
outgoing_payments_processing: list[str] = []
internal_payment_lock = asyncio.Lock()
async def pay_invoice(
*,
@ -443,15 +445,20 @@ async def get_payments_daily_stats(
return data
async def _pay_invoice(wallet, create_payment_model, conn):
payment = await _pay_internal_invoice(wallet, create_payment_model, conn)
async def _pay_invoice(
wallet: Wallet,
create_payment_model: CreatePayment,
conn: Optional[Connection] = None,
):
async with internal_payment_lock:
payment = await _pay_internal_invoice(wallet.id, create_payment_model, conn)
if not payment:
payment = await _pay_external_invoice(wallet, create_payment_model, conn)
return payment
async def _pay_internal_invoice(
wallet: Wallet,
wallet_id: str,
create_payment_model: CreatePayment,
conn: Optional[Connection] = None,
) -> Optional[Payment]:
@ -485,6 +492,11 @@ async def _pay_internal_invoice(
fee_reserve_total_msat = fee_reserve_total(amount_msat, internal=True)
create_payment_model.fee = abs(fee_reserve_total_msat)
# get the wallet again to make sure we have the latest balance
wallet = await get_wallet(wallet_id, conn=conn)
if not wallet:
raise PaymentError(f"Could not fetch wallet '{wallet_id}'.", status="failed")
print("### wallet.balance", wallet.balance_msat, wallet.balance)
if wallet.balance_msat < abs(amount_msat) + fee_reserve_total_msat:
raise PaymentError("Insufficient balance.", status="failed")

View File

@ -158,7 +158,7 @@ async def test_pay_twice_fast_b():
payment_request=payment_b.bolt11,
)
payments = await asyncio.gather(pay_first(), pay_second())
await asyncio.gather(pay_first(), pay_second())
wallet_one_after = await get_wallet(wallet_one.id)
assert wallet_one_after
@ -167,6 +167,7 @@ async def test_pay_twice_fast_b():
assert wallet_two_after
print("### wallet_two", wallet_two_after.balance)
@pytest.mark.anyio
async def test_fake_wallet_pay_external(
to_wallet: Wallet, external_funding_source: FakeWallet