diff --git a/cashu/core/models.py b/cashu/core/models.py index 0438165..8a506b0 100644 --- a/cashu/core/models.py +++ b/cashu/core/models.py @@ -141,6 +141,8 @@ class PostMintQuoteRequest(BaseModel): class PostMintQuoteResponse(BaseModel): quote: str # quote id request: str # input payment request + amount: Optional[int] # output amount (optional for backwards compat pre 0.16.6) + unit: Optional[str] # output unit (optional for backwards compat pre 0.16.6) state: Optional[str] # state of the quote (optional for backwards compat) expiry: Optional[int] # expiry of the quote pubkey: Optional[str] = None # NUT-20 quote lock pubkey @@ -222,6 +224,10 @@ class PostMeltQuoteRequest(BaseModel): class PostMeltQuoteResponse(BaseModel): quote: str # quote id amount: int # input amount + unit: Optional[str] # input unit (optional for backwards compat pre 0.16.6) + request: Optional[ + str + ] # output payment request (optional for backwards compat pre 0.16.6) fee_reserve: int # input fee reserve paid: Optional[bool] = ( None # whether the request has been paid # DEPRECATED as per NUT PR #136 diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index c3f6b40..d1bf37c 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -667,7 +667,10 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerTasks, LedgerFe if not payment_quote.checking_id: raise Exception("quote has no checking id") # verify that payment quote amount is as expected - if melt_quote.is_mpp and melt_quote.mpp_amount != payment_quote.amount.to(Unit.msat).amount: + if ( + melt_quote.is_mpp + and melt_quote.mpp_amount != payment_quote.amount.to(Unit.msat).amount + ): raise TransactionError("quote amount not as requested") # make sure the backend returned the amount with a correct unit if not payment_quote.amount.unit == unit: @@ -759,6 +762,8 @@ class Ledger(LedgerVerification, LedgerSpendingConditions, LedgerTasks, LedgerFe return PostMeltQuoteResponse( quote=quote.quote, amount=quote.amount, + unit=quote.unit, + request=quote.request, fee_reserve=quote.fee_reserve, paid=quote.paid, # deprecated state=quote.state.value, diff --git a/cashu/mint/router.py b/cashu/mint/router.py index 3b4c52d..0762548 100644 --- a/cashu/mint/router.py +++ b/cashu/mint/router.py @@ -163,8 +163,10 @@ async def mint_quote( logger.trace(f"> POST /v1/mint/quote/bolt11: payload={payload}") quote = await ledger.mint_quote(payload) resp = PostMintQuoteResponse( - request=quote.request, quote=quote.quote, + request=quote.request, + amount=quote.amount, + unit=quote.unit, paid=quote.paid, # deprecated state=quote.state.value, expiry=quote.expiry, @@ -190,6 +192,8 @@ async def get_mint_quote(request: Request, quote: str) -> PostMintQuoteResponse: resp = PostMintQuoteResponse( quote=mint_quote.quote, request=mint_quote.request, + amount=mint_quote.amount, + unit=mint_quote.unit, paid=mint_quote.paid, # deprecated state=mint_quote.state.value, expiry=mint_quote.expiry, @@ -290,6 +294,8 @@ async def get_melt_quote(request: Request, quote: str) -> PostMeltQuoteResponse: resp = PostMeltQuoteResponse( quote=melt_quote.quote, amount=melt_quote.amount, + unit=melt_quote.unit, + request=melt_quote.request, fee_reserve=melt_quote.fee_reserve, paid=melt_quote.paid, state=melt_quote.state.value, diff --git a/cashu/wallet/v1_api.py b/cashu/wallet/v1_api.py index a62c8a4..ff09730 100644 --- a/cashu/wallet/v1_api.py +++ b/cashu/wallet/v1_api.py @@ -469,6 +469,8 @@ class LedgerAPI(LedgerAPIDeprecated, SupportsAuth): return PostMeltQuoteResponse( quote=quote_id, amount=amount_sat, + unit=unit.name, + request=payment_request, fee_reserve=ret.fee or 0, paid=False, state=MeltQuoteState.unpaid.value, @@ -550,6 +552,8 @@ class LedgerAPI(LedgerAPIDeprecated, SupportsAuth): return PostMeltQuoteResponse( quote=quote, amount=0, + unit="sat", + request="lnbc0", fee_reserve=0, paid=ret.paid or False, state=( diff --git a/cashu/wallet/wallet_deprecated.py b/cashu/wallet/wallet_deprecated.py index 5b1a0b2..2c9b6dd 100644 --- a/cashu/wallet/wallet_deprecated.py +++ b/cashu/wallet/wallet_deprecated.py @@ -257,9 +257,12 @@ class LedgerAPIDeprecated(SupportsHttpxClient, SupportsMintURL): return_dict = resp.json() mint_response = GetMintResponse_deprecated.parse_obj(return_dict) decoded_invoice = bolt11.decode(mint_response.pr) + assert decoded_invoice.amount_msat, Exception("no amount in invoice") return PostMintQuoteResponse( quote=mint_response.hash, request=mint_response.pr, + amount=decoded_invoice.amount_msat // 1000, + unit="sat", paid=False, state=MintQuoteState.unpaid.value, expiry=decoded_invoice.date + (decoded_invoice.expiry or 0), diff --git a/tests/test_mint_api.py b/tests/test_mint_api.py index 284fc45..174f0b6 100644 --- a/tests/test_mint_api.py +++ b/tests/test_mint_api.py @@ -202,6 +202,9 @@ async def test_mint_quote(ledger: Ledger): resp_quote = PostMintQuoteResponse(**result) assert resp_quote.quote == result["quote"] assert resp_quote.state == MintQuoteState.unpaid.value + assert resp_quote.amount == 100 + assert resp_quote.unit == "sat" + assert resp_quote.request == result["request"] # check if DEPRECATED paid flag is also returned assert result["paid"] is False @@ -230,6 +233,9 @@ async def test_mint_quote(ledger: Ledger): resp_quote = PostMintQuoteResponse(**result2) assert resp_quote.quote == result["quote"] assert resp_quote.state == MintQuoteState.paid.value + assert resp_quote.amount == 100 + assert resp_quote.unit == "sat" + assert resp_quote.request == result["request"] # check if DEPRECATED paid flag is also returned assert result2["paid"] is True @@ -338,6 +344,9 @@ async def test_melt_quote_internal(ledger: Ledger, wallet: Wallet): assert resp_quote.payment_preimage is None assert resp_quote.change is None assert resp_quote.state == MeltQuoteState.unpaid.value + assert resp_quote.amount == 64 + assert resp_quote.unit == "sat" + assert resp_quote.request == request # check if DEPRECATED paid flag is also returned assert result["paid"] is False @@ -446,6 +455,9 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): assert resp_quote.payment_preimage is None assert resp_quote.change == [] assert resp_quote.state == MeltQuoteState.paid.value + assert resp_quote.amount == 64 + assert resp_quote.unit == "sat" + assert resp_quote.request == invoice_payment_request # check if DEPRECATED paid flag is also returned assert result["paid"] is True @@ -504,6 +516,9 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet): # deserialize the response resp_quote = PostMeltQuoteResponse(**result) assert resp_quote.quote == quote.quote + assert resp_quote.amount == 62 + assert resp_quote.unit == "sat" + assert resp_quote.request == invoice_payment_request assert resp_quote.payment_preimage is not None assert len(resp_quote.payment_preimage) == 64 assert resp_quote.change is not None