feat: add support for paying amountless BOLT11 invoices
Some checks are pending
LNbits CI / migration (3.12) (push) Blocked by required conditions
LNbits CI / openapi (push) Blocked by required conditions
LNbits CI / lint (push) Waiting to run
LNbits CI / test-api (, 3.10) (push) Blocked by required conditions
LNbits CI / migration (3.11) (push) Blocked by required conditions
LNbits CI / test-api (, 3.11) (push) Blocked by required conditions
LNbits CI / test-api (, 3.12) (push) Blocked by required conditions
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (push) Blocked by required conditions
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (push) Blocked by required conditions
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (push) Blocked by required conditions
LNbits CI / test-wallets (, 3.10) (push) Blocked by required conditions
LNbits CI / test-wallets (, 3.11) (push) Blocked by required conditions
LNbits CI / test-wallets (, 3.12) (push) Blocked by required conditions
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (push) Blocked by required conditions
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (push) Blocked by required conditions
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (push) Blocked by required conditions
LNbits CI / test-unit (, 3.10) (push) Blocked by required conditions
LNbits CI / test-unit (, 3.11) (push) Blocked by required conditions
LNbits CI / test-unit (, 3.12) (push) Blocked by required conditions
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (push) Blocked by required conditions
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (push) Blocked by required conditions
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (push) Blocked by required conditions
LNbits CI / migration (3.10) (push) Blocked by required conditions
LNbits CI / regtest (BoltzWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (CoreLightningRestWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (CoreLightningWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (EclairWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (LNbitsWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (LndRestWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (LndWallet, 3.10) (push) Blocked by required conditions
LNbits CI / jmeter (3.10) (push) Blocked by required conditions
codeql / analyze (push) Waiting to run
Some checks are pending
LNbits CI / migration (3.12) (push) Blocked by required conditions
LNbits CI / openapi (push) Blocked by required conditions
LNbits CI / lint (push) Waiting to run
LNbits CI / test-api (, 3.10) (push) Blocked by required conditions
LNbits CI / migration (3.11) (push) Blocked by required conditions
LNbits CI / test-api (, 3.11) (push) Blocked by required conditions
LNbits CI / test-api (, 3.12) (push) Blocked by required conditions
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (push) Blocked by required conditions
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (push) Blocked by required conditions
LNbits CI / test-api (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (push) Blocked by required conditions
LNbits CI / test-wallets (, 3.10) (push) Blocked by required conditions
LNbits CI / test-wallets (, 3.11) (push) Blocked by required conditions
LNbits CI / test-wallets (, 3.12) (push) Blocked by required conditions
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (push) Blocked by required conditions
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (push) Blocked by required conditions
LNbits CI / test-wallets (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (push) Blocked by required conditions
LNbits CI / test-unit (, 3.10) (push) Blocked by required conditions
LNbits CI / test-unit (, 3.11) (push) Blocked by required conditions
LNbits CI / test-unit (, 3.12) (push) Blocked by required conditions
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.10) (push) Blocked by required conditions
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.11) (push) Blocked by required conditions
LNbits CI / test-unit (postgres://lnbits:lnbits@0.0.0.0:5432/lnbits, 3.12) (push) Blocked by required conditions
LNbits CI / migration (3.10) (push) Blocked by required conditions
LNbits CI / regtest (BoltzWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (CoreLightningRestWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (CoreLightningWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (EclairWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (LNbitsWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (LndRestWallet, 3.10) (push) Blocked by required conditions
LNbits CI / regtest (LndWallet, 3.10) (push) Blocked by required conditions
LNbits CI / jmeter (3.10) (push) Blocked by required conditions
codeql / analyze (push) Waiting to run
Add ability to pay BOLT11 invoices that don't have an embedded amount by specifying the amount at payment time via the `amount_msat` parameter. Changes: - Add `Feature.amountless_invoice` to wallet base class for capability detection - Update `Wallet.pay_invoice()` signature with optional `amount_msat` parameter - Implement amountless invoice support in LND REST and LND gRPC wallets - Update payment service layer to validate and pass through amount_msat - Add `amount_msat` field to CreateInvoice API model - Update all wallet implementations with new method signature - Add tests for amountless invoice payment flow Usage: POST /api/v1/payments with `amount_msat` when paying amountless invoices 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
359e9d8b29
commit
8657e221c6
29 changed files with 697 additions and 45 deletions
|
|
@ -997,3 +997,71 @@ async def _create_some_payments(payment_count: int, client, payments_headers):
|
|||
data = response.json()
|
||||
assert data["labels"] == labels
|
||||
return payment_count
|
||||
|
||||
|
||||
################################ Amountless Invoices ################################
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_pay_amountless_invoice_with_amount(client, adminkey_headers_from):
|
||||
"""Test paying an amountless invoice by specifying amount_msat.
|
||||
|
||||
This tests the primary use case: receiving an amountless invoice from an
|
||||
external source and paying it with a specified amount.
|
||||
"""
|
||||
from lnbits.wallets import get_funding_source
|
||||
|
||||
# Create an amountless invoice directly using FakeWallet
|
||||
# (bypassing the service layer which blocks amountless invoices for creation)
|
||||
funding_source = get_funding_source()
|
||||
invoice_response = await funding_source.create_invoice(
|
||||
amount=0, memo="test_amountless_external"
|
||||
)
|
||||
assert invoice_response.ok
|
||||
assert invoice_response.payment_request
|
||||
|
||||
# Verify it's amountless
|
||||
decoded = bolt11.decode(invoice_response.payment_request)
|
||||
assert decoded.amount_msat is None
|
||||
|
||||
# Pay the amountless invoice with an explicit amount via API
|
||||
pay_data = {
|
||||
"out": True,
|
||||
"bolt11": invoice_response.payment_request,
|
||||
"amount_msat": 5000, # 5 sats in msat
|
||||
}
|
||||
response = await client.post(
|
||||
"/api/v1/payments", json=pay_data, headers=adminkey_headers_from
|
||||
)
|
||||
assert response.status_code < 300
|
||||
payment = response.json()
|
||||
assert "payment_hash" in payment
|
||||
assert payment["payment_hash"] == invoice_response.checking_id
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_pay_amountless_invoice_without_amount_fails(
|
||||
client, adminkey_headers_from
|
||||
):
|
||||
"""Test that paying an amountless invoice without amount_msat fails."""
|
||||
from lnbits.wallets import get_funding_source
|
||||
|
||||
# Create an amountless invoice directly using FakeWallet
|
||||
funding_source = get_funding_source()
|
||||
invoice_response = await funding_source.create_invoice(
|
||||
amount=0, memo="test_fail_amountless"
|
||||
)
|
||||
assert invoice_response.ok
|
||||
assert invoice_response.payment_request
|
||||
|
||||
# Try to pay without specifying amount - should fail
|
||||
pay_data = {
|
||||
"out": True,
|
||||
"bolt11": invoice_response.payment_request,
|
||||
}
|
||||
response = await client.post(
|
||||
"/api/v1/payments", json=pay_data, headers=adminkey_headers_from
|
||||
)
|
||||
# Should fail because amount is required for amountless invoices
|
||||
assert response.status_code >= 400
|
||||
assert "Amount required" in response.json().get("detail", "")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue