diff --git a/cashu/core/split.py b/cashu/core/split.py index 8f90c73..c6a366b 100644 --- a/cashu/core/split.py +++ b/cashu/core/split.py @@ -3,6 +3,8 @@ from typing import List def amount_split(amount: int) -> List[int]: """Given an amount returns a list of amounts returned e.g. 13 is [1, 4, 8].""" + if amount <= 0: + return [] bits_amt = bin(amount)[::-1][:-2] rv = [] for pos, bit in enumerate(bits_amt): diff --git a/cashu/lightning/blink.py b/cashu/lightning/blink.py index 9d18d67..3185b19 100644 --- a/cashu/lightning/blink.py +++ b/cashu/lightning/blink.py @@ -24,11 +24,13 @@ from .base import ( # according to https://github.com/GaloyMoney/galoy/blob/7e79cc27304de9b9c2e7d7f4fdd3bac09df23aac/core/api/src/domain/bitcoin/index.ts#L59 BLINK_MAX_FEE_PERCENT = 0.5 +# according to https://github.com/GaloyMoney/blink/blob/7e79cc27304de9b9c2e7d7f4fdd3bac09df23aac/core/api/src/domain/bitcoin/index.ts#L60C1-L60C41 +MINIMUM_FEE_MSAT = 10_000 DIRECTION_SEND = "SEND" DIRECTION_RECEIVE = "RECEIVE" PROBE_FEE_TIMEOUT_SEC = 1 -MINIMUM_FEE_MSAT = 2000 + INVOICE_RESULT_MAP = { "PENDING": PaymentResult.PENDING, diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index 9c08242..8a89ab6 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -385,7 +385,11 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerTasks, LedgerFe # we make sure that the fee is positive overpaid_fee = fee_provided - fee_paid - if overpaid_fee == 0 or outputs is None: + if overpaid_fee <= 0 or outputs is None: + if overpaid_fee < 0: + logger.error( + f"Overpaid fee is negative ({overpaid_fee}). This should not happen." + ) return [] logger.debug( diff --git a/tests/test_core.py b/tests/test_core.py index c2e8b57..bf03663 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -8,6 +8,8 @@ from cashu.wallet.helpers import deserialize_token_from_string def test_get_output_split(): assert amount_split(13) == [1, 4, 8] + assert amount_split(0) == [] + assert amount_split(-8) == [] def test_tokenv3_deserialize_get_attributes(): diff --git a/tests/test_mint_lightning_blink.py b/tests/test_mint_lightning_blink.py index 4461358..f216f23 100644 --- a/tests/test_mint_lightning_blink.py +++ b/tests/test_mint_lightning_blink.py @@ -190,7 +190,7 @@ async def test_blink_get_payment_status(): @respx.mock @pytest.mark.asyncio async def test_blink_get_payment_quote(): - # response says 1 sat fees but invoice (1000 sat) * 0.5% is 5 sat so we expect 5 sat + # response says 1 sat fees but invoice (1000 sat) * 0.5% is 5 sat so we expect MINIMUM_FEE_MSAT/1000 sat mock_response = {"data": {"lnInvoiceFeeProbe": {"amount": 1}}} respx.post(blink.endpoint).mock(return_value=Response(200, json=mock_response)) melt_quote_request = PostMeltQuoteRequest( @@ -199,7 +199,7 @@ async def test_blink_get_payment_quote(): quote = await blink.get_payment_quote(melt_quote_request) assert quote.checking_id == payment_request assert quote.amount == Amount(Unit.sat, 1000) # sat - assert quote.fee == Amount(Unit.sat, 5) # sat + assert quote.fee == Amount(Unit.sat, MINIMUM_FEE_MSAT // 1000) # msat # response says 10 sat fees but invoice (1000 sat) * 0.5% is 5 sat so we expect 10 sat mock_response = {"data": {"lnInvoiceFeeProbe": {"amount": 10}}} @@ -238,7 +238,7 @@ async def test_blink_get_payment_quote(): @respx.mock @pytest.mark.asyncio async def test_blink_get_payment_quote_backend_error(): - # response says error but invoice (1000 sat) * 0.5% is 5 sat so we expect 10 sat + # response says error but invoice (1000 sat) * 0.5% is 5 sat so we expect 10 sat (MINIMUM_FEE_MSAT) mock_response = {"data": {"lnInvoiceFeeProbe": {"errors": [{"message": "error"}]}}} respx.post(blink.endpoint).mock(return_value=Response(200, json=mock_response)) melt_quote_request = PostMeltQuoteRequest( @@ -247,4 +247,4 @@ async def test_blink_get_payment_quote_backend_error(): quote = await blink.get_payment_quote(melt_quote_request) assert quote.checking_id == payment_request assert quote.amount == Amount(Unit.sat, 1000) # sat - assert quote.fee == Amount(Unit.sat, 5) # sat + assert quote.fee == Amount(Unit.sat, MINIMUM_FEE_MSAT // 1000) # msat