diff --git a/cashu/core/base.py b/cashu/core/base.py index 66b4bce8..8f71eb9f 100644 --- a/cashu/core/base.py +++ b/cashu/core/base.py @@ -1,6 +1,7 @@ import base64 import json import math +import time from abc import ABC, abstractmethod from dataclasses import dataclass, field from enum import Enum @@ -260,20 +261,7 @@ def from_row(cls, row: Row): ) -# ------- LIGHTNING INVOICE ------- - - -class Invoice(BaseModel): - amount: int - bolt11: str - id: str - out: Union[None, bool] = None - payment_hash: Union[None, str] = None - preimage: Union[str, None] = None - issued: Union[None, bool] = False - paid: Union[None, bool] = False - time_created: Union[None, str, int, float] = "" - time_paid: Union[None, str, int, float] = "" +# ------- Quotes ------- class MeltQuoteState(Enum): @@ -297,9 +285,10 @@ class MeltQuote(LedgerEvent): created_time: Union[int, None] = None paid_time: Union[int, None] = None fee_paid: int = 0 - payment_preimage: str = "" + payment_preimage: Optional[str] = None expiry: Optional[int] = None change: Optional[List[BlindedSignature]] = None + mint: Optional[str] = None @classmethod def from_row(cls, row: Row): @@ -314,6 +303,8 @@ def from_row(cls, row: Row): paid_time = int(row["paid_time"].timestamp()) if row["paid_time"] else None expiry = int(row["expiry"].timestamp()) if row["expiry"] else None + payment_preimage = row.get("payment_preimage") or row.get("proof") # type: ignore + # parse change from row as json change = None if row["change"]: @@ -327,13 +318,30 @@ def from_row(cls, row: Row): unit=row["unit"], amount=row["amount"], fee_reserve=row["fee_reserve"], - state=MeltQuoteState[row["state"]], + state=MeltQuoteState(row["state"]), created_time=created_time, paid_time=paid_time, fee_paid=row["fee_paid"], change=change, expiry=expiry, - payment_preimage=row["proof"], + payment_preimage=payment_preimage, + ) + + @classmethod + def from_resp_wallet( + cls, melt_quote_resp, mint: str, amount: int, unit: str, request: str + ): + return cls( + quote=melt_quote_resp.quote, + method="bolt11", + request=request, + checking_id="", + unit=unit, + amount=amount, + fee_reserve=melt_quote_resp.fee_reserve, + state=MeltQuoteState(melt_quote_resp.state), + mint=mint, + change=melt_quote_resp.change, ) @property @@ -397,6 +405,7 @@ class MintQuote(LedgerEvent): created_time: Union[int, None] = None paid_time: Union[int, None] = None expiry: Optional[int] = None + mint: Optional[str] = None @classmethod def from_row(cls, row: Row): @@ -417,11 +426,26 @@ def from_row(cls, row: Row): checking_id=row["checking_id"], unit=row["unit"], amount=row["amount"], - state=MintQuoteState[row["state"]], + state=MintQuoteState(row["state"]), created_time=created_time, paid_time=paid_time, ) + @classmethod + def from_resp_wallet(cls, mint_quote_resp, mint: str, amount: int, unit: str): + return cls( + quote=mint_quote_resp.quote, + method="bolt11", + request=mint_quote_resp.request, + checking_id="", + unit=unit, + amount=amount, + state=MintQuoteState(mint_quote_resp.state), + mint=mint, + expiry=mint_quote_resp.expiry, + created_time=int(time.time()), + ) + @property def identifier(self) -> str: """Implementation of the abstract method from LedgerEventManager""" diff --git a/cashu/core/db.py b/cashu/core/db.py index 8f7baa03..7a069d60 100644 --- a/cashu/core/db.py +++ b/cashu/core/db.py @@ -65,6 +65,7 @@ def big_int(self) -> str: def table_with_schema(self, table: str): return f"{self.references_schema if self.schema else ''}{table}" + # https://docs.sqlalchemy.org/en/14/core/connections.html#sqlalchemy.engine.CursorResult class Connection(Compat): def __init__(self, conn: AsyncSession, txn, typ, name, schema): @@ -82,7 +83,9 @@ def rewrite_query(self, query) -> TextClause: async def fetchall(self, query: str, values: dict = {}): result = await self.conn.execute(self.rewrite_query(query), values) - return [r._mapping for r in result.all()] # will return [] if result list is empty + return [ + r._mapping for r in result.all() + ] # will return [] if result list is empty async def fetchone(self, query: str, values: dict = {}): result = await self.conn.execute(self.rewrite_query(query), values) @@ -134,13 +137,13 @@ def __init__(self, db_name: str, db_location: str): if not settings.db_connection_pool: kwargs["poolclass"] = NullPool elif self.type == POSTGRES: - kwargs["poolclass"] = AsyncAdaptedQueuePool # type: ignore[assignment] - kwargs["pool_size"] = 50 # type: ignore[assignment] - kwargs["max_overflow"] = 100 # type: ignore[assignment] + kwargs["poolclass"] = AsyncAdaptedQueuePool # type: ignore[assignment] + kwargs["pool_size"] = 50 # type: ignore[assignment] + kwargs["max_overflow"] = 100 # type: ignore[assignment] self.engine = create_async_engine(database_uri, **kwargs) self.async_session = sessionmaker( - self.engine, + self.engine, # type: ignore expire_on_commit=False, class_=AsyncSession, # type: ignore ) diff --git a/cashu/mint/crud.py b/cashu/mint/crud.py index c07e17da..1ddb8aa6 100644 --- a/cashu/mint/crud.py +++ b/cashu/mint/crud.py @@ -304,7 +304,7 @@ async def get_promise( """, {"b_": str(b_)}, ) - return BlindedSignature.from_row(row) if row else None + return BlindedSignature.from_row(row) if row else None # type: ignore async def get_promises( self, @@ -320,7 +320,7 @@ async def get_promises( """, {f"b_{i}": b_s[i] for i in range(len(b_s))}, ) - return [BlindedSignature.from_row(r) for r in rows] if rows else [] + return [BlindedSignature.from_row(r) for r in rows] if rows else [] # type: ignore async def invalidate_proof( self, @@ -455,7 +455,7 @@ async def store_mint_quote( "amount": quote.amount, "paid": quote.paid, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table) "issued": quote.issued, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table) - "state": quote.state.name, + "state": quote.state.value, "created_time": db.to_timestamp( db.timestamp_from_seconds(quote.created_time) or "" ), @@ -497,7 +497,7 @@ async def get_mint_quote( ) if row is None: return None - return MintQuote.from_row(row) if row else None + return MintQuote.from_row(row) if row else None # type: ignore async def get_mint_quote_by_request( self, @@ -513,7 +513,7 @@ async def get_mint_quote_by_request( """, {"request": request}, ) - return MintQuote.from_row(row) if row else None + return MintQuote.from_row(row) if row else None # type: ignore async def update_mint_quote( self, @@ -525,7 +525,7 @@ async def update_mint_quote( await (conn or db).execute( f"UPDATE {db.table_with_schema('mint_quotes')} SET state = :state, paid_time = :paid_time WHERE quote = :quote", { - "state": quote.state.name, + "state": quote.state.value, "paid_time": db.to_timestamp( db.timestamp_from_seconds(quote.paid_time) or "" ), @@ -554,7 +554,7 @@ async def store_melt_quote( "unit": quote.unit, "amount": quote.amount, "fee_reserve": quote.fee_reserve or 0, - "state": quote.state.name, + "state": quote.state.value, "paid": quote.paid, # this is deprecated! we need to store it because we have a NOT NULL constraint | we could also remove the column but sqlite doesn't support that (we would have to make a new table) "created_time": db.to_timestamp( db.timestamp_from_seconds(quote.created_time) or "" @@ -631,7 +631,7 @@ async def update_melt_quote( UPDATE {db.table_with_schema('melt_quotes')} SET state = :state, fee_paid = :fee_paid, paid_time = :paid_time, proof = :proof, change = :change, checking_id = :checking_id WHERE quote = :quote """, { - "state": quote.state.name, + "state": quote.state.value, "fee_paid": quote.fee_paid, "paid_time": db.to_timestamp( db.timestamp_from_seconds(quote.paid_time) or "" diff --git a/cashu/mint/migrations.py b/cashu/mint/migrations.py index 9186afa1..e4a559cd 100644 --- a/cashu/mint/migrations.py +++ b/cashu/mint/migrations.py @@ -1,7 +1,7 @@ import copy from typing import Dict, List -from ..core.base import MintKeyset, Proof +from ..core.base import MeltQuoteState, MintKeyset, MintQuoteState, Proof from ..core.crypto.keys import derive_keyset_id, derive_keyset_id_deprecated from ..core.db import Connection, Database from ..core.settings import settings @@ -826,3 +826,15 @@ async def m021_add_change_and_expiry_to_melt_quotes(db: Database): await conn.execute( f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN expiry TIMESTAMP" ) + + +async def m022_quote_set_states_to_values(db: Database): + async with db.connect() as conn: + for melt_quote_states in MeltQuoteState: + await conn.execute( + f"UPDATE {db.table_with_schema('melt_quotes')} SET state = '{melt_quote_states.value}' WHERE state = '{melt_quote_states.name}'" + ) + for mint_quote_states in MintQuoteState: + await conn.execute( + f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{mint_quote_states.value}' WHERE state = '{mint_quote_states.name}'" + ) diff --git a/cashu/wallet/api/responses.py b/cashu/wallet/api/responses.py index db3532e0..1c6fdf4c 100644 --- a/cashu/wallet/api/responses.py +++ b/cashu/wallet/api/responses.py @@ -2,23 +2,13 @@ from pydantic import BaseModel -from ...core.base import Invoice - - -class PayResponse(BaseModel): - ok: Optional[bool] = None - - -class InvoiceResponse(BaseModel): - amount: Optional[int] = None - invoice: Optional[Invoice] = None - id: Optional[str] = None +from ...core.base import MeltQuote, MintQuote class SwapResponse(BaseModel): outgoing_mint: str incoming_mint: str - invoice: Invoice + mint_quote: MintQuote balances: Dict @@ -56,7 +46,8 @@ class LocksResponse(BaseModel): class InvoicesResponse(BaseModel): - invoices: List[Invoice] + mint_quotes: List[MintQuote] + melt_quotes: List[MeltQuote] class WalletsResponse(BaseModel): diff --git a/cashu/wallet/api/router.py b/cashu/wallet/api/router.py index 05ec5a62..c495b616 100644 --- a/cashu/wallet/api/router.py +++ b/cashu/wallet/api/router.py @@ -19,7 +19,11 @@ ) from ...nostr.client.client import NostrClient from ...tor.tor import TorProxy -from ...wallet.crud import get_lightning_invoices, get_reserved_proofs +from ...wallet.crud import ( + get_bolt11_melt_quotes, + get_bolt11_mint_quotes, + get_reserved_proofs, +) from ...wallet.helpers import ( deserialize_token_from_string, init_wallet, @@ -141,7 +145,7 @@ async def create_invoice( response_model=PaymentStatus, ) async def invoice_state( - payment_hash: str = Query(default=None, description="Payment hash of paid invoice"), + payment_request: str = Query(default=None, description="Payment request to check"), mint: str = Query( default=None, description="Mint URL to create an invoice at (None for default mint)", @@ -150,7 +154,7 @@ async def invoice_state( global wallet if mint: wallet = await mint_wallet(mint) - state = await wallet.get_invoice_status(payment_hash) + state = await wallet.get_invoice_status(payment_request) return state @@ -185,11 +189,11 @@ async def swap( raise Exception("mints for swap have to be different") # request invoice from incoming mint - invoice = await incoming_wallet.request_mint(amount) + mint_quote = await incoming_wallet.request_mint(amount) # pay invoice from outgoing mint await outgoing_wallet.load_proofs(reload=True) - quote = await outgoing_wallet.melt_quote(invoice.bolt11) + quote = await outgoing_wallet.melt_quote(mint_quote.request) total_amount = quote.amount + quote.fee_reserve if outgoing_wallet.available_balance < total_amount: raise Exception("balance too low") @@ -198,17 +202,17 @@ async def swap( outgoing_wallet.proofs, total_amount, set_reserved=True ) await outgoing_wallet.melt( - send_proofs, invoice.bolt11, quote.fee_reserve, quote.quote + send_proofs, mint_quote.request, quote.fee_reserve, quote.quote ) # mint token in incoming mint - await incoming_wallet.mint(amount, id=invoice.id) + await incoming_wallet.mint(amount, quote_id=mint_quote.quote) await incoming_wallet.load_proofs(reload=True) mint_balances = await incoming_wallet.balance_per_minturl() return SwapResponse( outgoing_mint=outgoing_mint, incoming_mint=incoming_mint, - invoice=invoice, + mint_quote=mint_quote, balances=mint_balances, ) @@ -386,8 +390,9 @@ async def locks(): "/invoices", name="List all pending invoices", response_model=InvoicesResponse ) async def invoices(): - invoices = await get_lightning_invoices(db=wallet.db) - return InvoicesResponse(invoices=invoices) + mint_quotes = await get_bolt11_mint_quotes(db=wallet.db) + melt_quotes = await get_bolt11_melt_quotes(db=wallet.db) + return InvoicesResponse(mint_quotes=mint_quotes, melt_quotes=melt_quotes) @router.get( diff --git a/cashu/wallet/cli/cli.py b/cashu/wallet/cli/cli.py index a1a723f1..85e0b1b7 100644 --- a/cashu/wallet/cli/cli.py +++ b/cashu/wallet/cli/cli.py @@ -15,7 +15,15 @@ from click import Context from loguru import logger -from ...core.base import Invoice, Method, MintQuoteState, TokenV4, Unit +from ...core.base import ( + MeltQuote, + MeltQuoteState, + Method, + MintQuote, + MintQuoteState, + TokenV4, + Unit, +) from ...core.helpers import sum_proofs from ...core.json_rpc.base import JSONRPCNotficationParams from ...core.logging import configure_logger @@ -24,8 +32,9 @@ from ...nostr.client.client import NostrClient from ...tor.tor import TorProxy from ...wallet.crud import ( - get_lightning_invoice, - get_lightning_invoices, + get_bolt11_melt_quotes, + get_bolt11_mint_quote, + get_bolt11_mint_quotes, get_reserved_proofs, get_seed_and_mnemonic, ) @@ -302,7 +311,7 @@ async def invoice( ) paid = False - invoice_nonlocal: Union[None, Invoice] = None + invoice_nonlocal: Union[None, MintQuote] = None subscription_nonlocal: Union[None, SubscriptionManager] = None def mint_invoice_callback(msg: JSONRPCNotficationParams): @@ -318,20 +327,24 @@ def mint_invoice_callback(msg: JSONRPCNotficationParams): if paid: return try: - quote = PostMintQuoteResponse.parse_obj(msg.payload) + ws_quote_resp = PostMintQuoteResponse.parse_obj(msg.payload) except Exception: return - logger.debug(f"Received callback for quote: {quote}") + logger.debug( + f"Received callback for quote: {ws_quote_resp.quote}: state {ws_quote_resp.state}" + ) # we need to sleep to give the callback map some time to be populated time.sleep(0.1) if ( - (quote.paid or quote.state == MintQuoteState.paid.value) - and quote.request == invoice.bolt11 + (ws_quote_resp.state == MintQuoteState.paid.value) + and ws_quote_resp.request == mint_quote.request and msg.subId in subscription.callback_map.keys() ): try: asyncio.run( - wallet.mint(int(amount), split=optional_split, id=invoice.id) + wallet.mint( + int(amount), split=optional_split, quote_id=mint_quote.quote + ) ) # set paid so we won't react to any more callbacks paid = True @@ -348,21 +361,21 @@ def mint_invoice_callback(msg: JSONRPCNotficationParams): Method["bolt11"], wallet.unit ) if mint_supports_websockets and not no_check: - invoice, subscription = await wallet.request_mint_with_callback( + mint_quote, subscription = await wallet.request_mint_with_callback( amount, callback=mint_invoice_callback, memo=memo ) - invoice_nonlocal, subscription_nonlocal = invoice, subscription + invoice_nonlocal, subscription_nonlocal = mint_quote, subscription else: - invoice = await wallet.request_mint(amount, memo=memo) - if invoice.bolt11: + mint_quote = await wallet.request_mint(amount, memo=memo) + if mint_quote.request: print("") print(f"Pay invoice to mint {wallet.unit.str(amount)}:") print("") - print(f"Invoice: {invoice.bolt11}") + print(f"Invoice: {mint_quote.request}") print("") print( "You can use this command to check the invoice: cashu invoice" - f" {amount} --id {invoice.id}" + f" {amount} --id {mint_quote.quote}" ) if no_check: return @@ -381,9 +394,11 @@ def mint_invoice_callback(msg: JSONRPCNotficationParams): while time.time() < check_until and not paid: await asyncio.sleep(5) try: - mint_quote_resp = await wallet.get_mint_quote(invoice.id) + mint_quote_resp = await wallet.get_mint_quote(mint_quote.quote) if mint_quote_resp.state == MintQuoteState.paid.value: - await wallet.mint(amount, split=optional_split, id=invoice.id) + await wallet.mint( + amount, split=optional_split, quote_id=mint_quote.quote + ) paid = True else: print(".", end="", flush=True) @@ -403,7 +418,7 @@ def mint_invoice_callback(msg: JSONRPCNotficationParams): # user paid invoice before and wants to check the quote id elif amount and id: - await wallet.mint(amount, split=optional_split, id=id) + await wallet.mint(amount, split=optional_split, quote_id=id) # close open subscriptions so we can exit try: @@ -422,10 +437,10 @@ def mint_invoice_callback(msg: JSONRPCNotficationParams): @coro async def swap(ctx: Context): print("Select the mint to swap from:") - outgoing_wallet = await get_mint_wallet(ctx, force_select=True) + outgoing_wallet: Wallet = await get_mint_wallet(ctx, force_select=True) print("Select the mint to swap to:") - incoming_wallet = await get_mint_wallet(ctx, force_select=True) + incoming_wallet: Wallet = await get_mint_wallet(ctx, force_select=True) await incoming_wallet.load_mint() await outgoing_wallet.load_mint() @@ -437,22 +452,25 @@ async def swap(ctx: Context): assert amount > 0, "amount is not positive" # request invoice from incoming mint - invoice = await incoming_wallet.request_mint(amount) + mint_quote = await incoming_wallet.request_mint(amount) # pay invoice from outgoing mint - quote = await outgoing_wallet.melt_quote(invoice.bolt11) - total_amount = quote.amount + quote.fee_reserve + melt_quote_resp = await outgoing_wallet.melt_quote(mint_quote.request) + total_amount = melt_quote_resp.amount + melt_quote_resp.fee_reserve if outgoing_wallet.available_balance < total_amount: raise Exception("balance too low") send_proofs, fees = await outgoing_wallet.select_to_send( outgoing_wallet.proofs, total_amount, set_reserved=True ) await outgoing_wallet.melt( - send_proofs, invoice.bolt11, quote.fee_reserve, quote.quote + send_proofs, + mint_quote.request, + melt_quote_resp.fee_reserve, + melt_quote_resp.quote, ) # mint token in incoming mint - await incoming_wallet.mint(amount, id=invoice.id) + await incoming_wallet.mint(amount, quote_id=mint_quote.quote) await incoming_wallet.load_proofs(reload=True) await print_mint_balances(incoming_wallet, show_mints=True) @@ -875,67 +893,85 @@ async def invoices(ctx, paid: bool, unpaid: bool, pending: bool, mint: bool): if mint: await wallet.load_mint() - paid_arg = None + melt_state: MeltQuoteState | None = None + mint_state: MintQuoteState | None = None if unpaid: - paid_arg = False + melt_state = MeltQuoteState.unpaid + mint_state = MintQuoteState.unpaid elif paid: - paid_arg = True + melt_state = MeltQuoteState.paid + mint_state = MintQuoteState.paid + + melt_quotes = await get_bolt11_melt_quotes( + db=wallet.db, + state=melt_state, + ) - invoices = await get_lightning_invoices( + mint_quotes = await get_bolt11_mint_quotes( db=wallet.db, - paid=paid_arg, - pending=pending or None, + state=mint_state, ) - if len(invoices) == 0: + if len(melt_quotes) == 0 and len(mint_quotes) == 0: print("No invoices found.") return - async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[Invoice]: + async def _try_to_mint_pending_invoice(amount: int, id: str) -> Optional[MintQuote]: try: - await wallet.mint(amount, id) - return await get_lightning_invoice(db=wallet.db, id=id) + proofs = await wallet.mint(amount, id) + print(f"Received {wallet.unit.str(sum_proofs(proofs))}") + return await get_bolt11_mint_quote(db=wallet.db, quote=id) except Exception as e: - logger.error(f"Could not mint pending invoice [{id}]: {e}") + logger.error(f"Could not mint pending invoice: {e}") return None - def _print_invoice_info(invoice: Invoice): + def _print_quote_info( + quote: MintQuote | MeltQuote | None, counter: int | None = None + ): print("\n--------------------------\n") - print(f"Amount: {abs(invoice.amount)}") - print(f"ID: {invoice.id}") - print(f"Paid: {invoice.paid}") - print(f"Incoming: {invoice.amount > 0}") - - if invoice.preimage: - print(f"Preimage: {invoice.preimage}") - if invoice.time_created: + if counter: + print(f"#{counter}", end=" ") + if isinstance(quote, MintQuote): + print("Mint quote (incoming invoice)") + elif isinstance(quote, MeltQuote): + print("Melt quote (outgoing invoice)") + else: + return + print(f"Amount: {abs(quote.amount)}") + print(f"Mint: {quote.mint}") + print(f"ID: {quote.quote}") + print(f"State: {quote.state}") + + if isinstance(quote, MeltQuote): + if quote.payment_preimage: + print(f"Preimage: {quote.payment_preimage}") + if quote.created_time: d = datetime.fromtimestamp( - int(float(invoice.time_created)), timezone.utc + int(float(quote.created_time)), timezone.utc ).strftime("%Y-%m-%d %H:%M:%S") print(f"Created at: {d}") - if invoice.time_paid: + if quote.paid_time: d = datetime.fromtimestamp( - (int(float(invoice.time_paid))), timezone.utc + (int(float(quote.paid_time))), timezone.utc ).strftime("%Y-%m-%d %H:%M:%S") print(f"Paid at: {d}") - print(f"\nPayment request: {invoice.bolt11}") + print(f"\nPayment request: {quote.request}") invoices_printed_count = 0 - for invoice in invoices: - is_pending_invoice = invoice.out is False and invoice.paid is False - if is_pending_invoice and mint: + for melt_quote in melt_quotes: + _print_quote_info(melt_quote, invoices_printed_count + 1) + invoices_printed_count += 1 + + for mint_quote in mint_quotes: + if mint_quote.state == MintQuoteState.unpaid and mint: # Tries to mint pending invoice - updated_invoice = await _try_to_mint_pending_invoice( - invoice.amount, invoice.id + mint_quote_pay = await _try_to_mint_pending_invoice( + mint_quote.amount, mint_quote.quote ) - # If the mint ran successfully and we are querying for pending or unpaid invoices, do not print it - if pending or unpaid: + # If minting was successful, we don't need to print this invoice + if mint_quote_pay: continue - # Otherwise, print the invoice with updated values - if updated_invoice: - invoice = updated_invoice - - _print_invoice_info(invoice) + _print_quote_info(mint_quote, invoices_printed_count + 1) invoices_printed_count += 1 if invoices_printed_count == 0: diff --git a/cashu/wallet/crud.py b/cashu/wallet/crud.py index 62b5456e..1cf62a2f 100644 --- a/cashu/wallet/crud.py +++ b/cashu/wallet/crud.py @@ -2,7 +2,14 @@ import time from typing import Any, Dict, List, Optional, Tuple -from ..core.base import Invoice, Proof, WalletKeyset +from ..core.base import ( + MeltQuote, + MeltQuoteState, + MintQuote, + MintQuoteState, + Proof, + WalletKeyset, +) from ..core.db import Connection, Database @@ -217,7 +224,7 @@ async def get_keysets( """, values, ) - return [WalletKeyset.from_row(r) for r in rows] + return [WalletKeyset.from_row(r) for r in rows] # type: ignore async def update_keyset( @@ -238,83 +245,78 @@ async def update_keyset( ) -async def store_lightning_invoice( +async def store_bolt11_mint_quote( db: Database, - invoice: Invoice, + quote: MintQuote, conn: Optional[Connection] = None, ) -> None: await (conn or db).execute( """ - INSERT INTO invoices - (amount, bolt11, id, payment_hash, preimage, paid, time_created, time_paid, out) - VALUES (:amount, :bolt11, :id, :payment_hash, :preimage, :paid, :time_created, :time_paid, :out) + INSERT INTO bolt11_mint_quotes + (quote, mint, method, request, checking_id, unit, amount, state, created_time, paid_time, expiry) + VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :state, :created_time, :paid_time, :expiry) """, { - "amount": invoice.amount, - "bolt11": invoice.bolt11, - "id": invoice.id, - "payment_hash": invoice.payment_hash, - "preimage": invoice.preimage, - "paid": invoice.paid, - "time_created": invoice.time_created, - "time_paid": invoice.time_paid, - "out": invoice.out, + "quote": quote.quote, + "mint": quote.mint, + "method": quote.method, + "request": quote.request, + "checking_id": quote.checking_id, + "unit": quote.unit, + "amount": quote.amount, + "state": quote.state.value, + "created_time": quote.created_time, + "paid_time": quote.paid_time, + "expiry": quote.expiry, }, ) -async def get_lightning_invoice( - *, +async def get_bolt11_mint_quote( db: Database, - id: str = "", - payment_hash: str = "", - out: Optional[bool] = None, + quote: str | None = None, + request: str | None = None, conn: Optional[Connection] = None, -) -> Optional[Invoice]: +) -> Optional[MintQuote]: + if not quote and not request: + raise ValueError("quote or request must be provided") clauses = [] values: Dict[str, Any] = {} - if id: - clauses.append("id = :id") - values["id"] = id - if payment_hash: - clauses.append("payment_hash = :payment_hash") - values["payment_hash"] = payment_hash - if out is not None: - clauses.append("out = :out") - values["out"] = out + if quote: + clauses.append("quote = :quote") + values["quote"] = quote + if request: + clauses.append("request = :request") + values["request"] = request where = "" if clauses: where = f"WHERE {' AND '.join(clauses)}" - query = f""" - SELECT * from invoices - {where} - """ + row = await (conn or db).fetchone( - query, + f""" + SELECT * from bolt11_mint_quotes + {where} + """, values, ) - return Invoice(**row) if row else None + return MintQuote.from_row(row) if row else None # type: ignore -async def get_lightning_invoices( +async def get_bolt11_mint_quotes( db: Database, - paid: Optional[bool] = None, - pending: Optional[bool] = None, + mint: Optional[str] = None, + state: Optional[MintQuoteState] = None, conn: Optional[Connection] = None, -) -> List[Invoice]: +) -> List[MintQuote]: clauses = [] values: Dict[str, Any] = {} - - if paid is not None and not pending: - clauses.append("paid = :paid") - values["paid"] = paid - - if pending: - clauses.append("paid = :paid") - values["paid"] = False - clauses.append("out = :out") - values["out"] = False + if mint: + clauses.append("mint = :mint") + values["mint"] = mint + if state: + clauses.append("state = :state") + values["state"] = state.value where = "" if clauses: @@ -322,37 +324,149 @@ async def get_lightning_invoices( rows = await (conn or db).fetchall( f""" - SELECT * from invoices + SELECT * from bolt11_mint_quotes {where} """, values, ) - return [Invoice(**r) for r in rows] + return [MintQuote.from_row(r) for r in rows] # type: ignore + + +async def update_bolt11_mint_quote( + db: Database, + quote: str, + state: MintQuoteState, + paid_time: int, + conn: Optional[Connection] = None, +) -> None: + await (conn or db).execute( + """ + UPDATE bolt11_mint_quotes + SET state = :state, paid_time = :paid_time + WHERE quote = :quote + """, + { + "state": state.value, + "paid_time": paid_time, + "quote": quote, + }, + ) -async def update_lightning_invoice( +async def store_bolt11_melt_quote( db: Database, - id: str, - paid: bool, - time_paid: Optional[int] = None, - preimage: Optional[str] = None, + quote: MeltQuote, conn: Optional[Connection] = None, ) -> None: + await (conn or db).execute( + """ + INSERT INTO bolt11_melt_quotes + (quote, mint, method, request, checking_id, unit, amount, fee_reserve, state, created_time, paid_time, fee_paid, payment_preimage, expiry, change) + VALUES (:quote, :mint, :method, :request, :checking_id, :unit, :amount, :fee_reserve, :state, :created_time, :paid_time, :fee_paid, :payment_preimage, :expiry, :change) + """, + { + "quote": quote.quote, + "mint": quote.mint, + "method": quote.method, + "request": quote.request, + "checking_id": quote.checking_id, + "unit": quote.unit, + "amount": quote.amount, + "fee_reserve": quote.fee_reserve, + "state": quote.state.value, + "created_time": quote.created_time, + "paid_time": quote.paid_time, + "fee_paid": quote.fee_paid, + "payment_preimage": quote.payment_preimage, + "expiry": quote.expiry, + "change": ( + json.dumps([c.dict() for c in quote.change]) if quote.change else "" + ), + }, + ) + + +async def get_bolt11_melt_quote( + db: Database, + quote: Optional[str] = None, + request: Optional[str] = None, + conn: Optional[Connection] = None, +) -> Optional[MeltQuote]: + if not quote and not request: + raise ValueError("quote or request must be provided") clauses = [] values: Dict[str, Any] = {} - clauses.append("paid = :paid") - values["paid"] = paid + if quote: + clauses.append("quote = :quote") + values["quote"] = quote + if request: + clauses.append("request = :request") + values["request"] = request - if time_paid: - clauses.append("time_paid = :time_paid") - values["time_paid"] = time_paid - if preimage: - clauses.append("preimage = :preimage") - values["preimage"] = preimage + where = "" + if clauses: + where = f"WHERE {' AND '.join(clauses)}" + row = await (conn or db).fetchone( + f""" + SELECT * from bolt11_melt_quotes + {where} + """, + values, + ) + + return MeltQuote.from_row(row) if row else None # type: ignore + + +async def get_bolt11_melt_quotes( + db: Database, + mint: Optional[str] = None, + state: Optional[MeltQuoteState] = None, + conn: Optional[Connection] = None, +) -> List[MeltQuote]: + clauses = [] + values: Dict[str, Any] = {} + if mint: + clauses.append("mint = :mint") + values["mint"] = mint + if state: + clauses.append("state = :state") + values["state"] = state.value + + where = "" + if clauses: + where = f"WHERE {' AND '.join(clauses)}" + rows = await (conn or db).fetchall( + f""" + SELECT * from bolt11_melt_quotes + {where} + """, + values, + ) + return [MeltQuote.from_row(r) for r in rows] # type: ignore + +async def update_bolt11_melt_quote( + db: Database, + quote: str, + state: MeltQuoteState, + paid_time: int, + fee_paid: int, + payment_preimage: str, + conn: Optional[Connection] = None, +) -> None: await (conn or db).execute( - f"UPDATE invoices SET {', '.join(clauses)} WHERE id = :id", - {**values, "id": id}, + """ + UPDATE bolt11_melt_quotes + SET state = :state, paid_time = :paid_time, fee_paid = :fee_paid, payment_preimage = :payment_preimage + WHERE quote = :quote + """, + { + "state": state.value, + "paid_time": paid_time, + "fee_paid": fee_paid, + "payment_preimage": payment_preimage, + "quote": quote, + }, ) @@ -423,7 +537,7 @@ async def get_nostr_last_check_timestamp( """, {"type": "dm"}, ) - return row[0] if row else None + return row[0] if row else None # type: ignore async def get_seed_and_mnemonic( diff --git a/cashu/wallet/lightning/lightning.py b/cashu/wallet/lightning/lightning.py index a3bb2805..8f630b9a 100644 --- a/cashu/wallet/lightning/lightning.py +++ b/cashu/wallet/lightning/lightning.py @@ -12,7 +12,11 @@ PaymentStatus, StatusResponse, ) -from ...wallet.crud import get_lightning_invoice, get_proofs +from ...wallet.crud import ( + get_bolt11_melt_quote, + get_bolt11_mint_quote, + get_proofs, +) from ..wallet import Wallet @@ -47,21 +51,22 @@ async def create_invoice( Returns: str: invoice """ - invoice = await self.request_mint(amount, memo) + mint_quote = await self.request_mint(amount, memo) return InvoiceResponse( - ok=True, payment_request=invoice.bolt11, checking_id=invoice.payment_hash + ok=True, + payment_request=mint_quote.request, ) - async def pay_invoice(self, pr: str) -> PaymentResponse: + async def pay_invoice(self, request: str) -> PaymentResponse: """Pay lightning invoice Args: - pr (str): bolt11 payment request + request (str): bolt11 payment request Returns: PaymentResponse: containing details of the operation """ - quote = await self.melt_quote(pr) + quote = await self.melt_quote(request) total_amount = quote.amount + quote.fee_reserve assert total_amount > 0, "amount is not positive" if self.available_balance < total_amount: @@ -69,13 +74,13 @@ async def pay_invoice(self, pr: str) -> PaymentResponse: return PaymentResponse(result=PaymentResult.FAILED) _, send_proofs = await self.swap_to_send(self.proofs, total_amount) try: - resp = await self.melt(send_proofs, pr, quote.fee_reserve, quote.quote) + resp = await self.melt(send_proofs, request, quote.fee_reserve, quote.quote) if resp.change: fees_paid_sat = quote.fee_reserve - sum_promises(resp.change) else: fees_paid_sat = quote.fee_reserve - invoice_obj = bolt11.decode(pr) + invoice_obj = bolt11.decode(request) return PaymentResponse( result=PaymentResult.SETTLED, checking_id=invoice_obj.payment_hash, @@ -86,55 +91,49 @@ async def pay_invoice(self, pr: str) -> PaymentResponse: print("Exception:", e) return PaymentResponse(result=PaymentResult.FAILED, error_message=str(e)) - async def get_invoice_status(self, payment_hash: str) -> PaymentStatus: + async def get_invoice_status(self, request: str) -> PaymentStatus: """Get lightning invoice status (incoming) Args: - invoice (str): lightning invoice + request (str): lightning invoice request Returns: str: status """ - invoice = await get_lightning_invoice( - db=self.db, payment_hash=payment_hash, out=False - ) - if not invoice: + mint_quote = await get_bolt11_mint_quote(db=self.db, request=request) + if not mint_quote: return PaymentStatus(result=PaymentResult.UNKNOWN) - if invoice.paid: + if mint_quote.paid: return PaymentStatus(result=PaymentResult.SETTLED) try: # to check the invoice state, we try minting tokens - await self.mint(invoice.amount, id=invoice.id) + await self.mint(mint_quote.amount, quote_id=mint_quote.quote) return PaymentStatus(result=PaymentResult.SETTLED) except Exception as e: print(e) return PaymentStatus(result=PaymentResult.FAILED) - async def get_payment_status(self, payment_hash: str) -> PaymentStatus: + async def get_payment_status(self, request: str) -> PaymentStatus: """Get lightning payment status (outgoing) Args: - payment_hash (str): lightning invoice payment_hash + request (str): lightning invoice request Returns: str: status """ - # NOTE: consider adding this in wallet.py and update invoice state to paid in DB - - invoice = await get_lightning_invoice( - db=self.db, payment_hash=payment_hash, out=True - ) + melt_quote = await get_bolt11_melt_quote(db=self.db, request=request) - if not invoice: + if not melt_quote: return PaymentStatus( result=PaymentResult.FAILED ) # "invoice not found (in db)" - if invoice.paid: + if melt_quote.paid: return PaymentStatus( - result=PaymentResult.SETTLED, preimage=invoice.preimage + result=PaymentResult.SETTLED, preimage=melt_quote.payment_preimage ) # "paid (in db)" - proofs = await get_proofs(db=self.db, melt_id=invoice.id) + proofs = await get_proofs(db=self.db, melt_id=melt_quote.quote) if not proofs: return PaymentStatus( result=PaymentResult.FAILED diff --git a/cashu/wallet/migrations.py b/cashu/wallet/migrations.py index 41937318..8587caf6 100644 --- a/cashu/wallet/migrations.py +++ b/cashu/wallet/migrations.py @@ -245,79 +245,44 @@ async def m012_add_fee_to_keysets(db: Database): await conn.execute("UPDATE keysets SET input_fee_ppk = 0") -# # async def m020_add_state_to_mint_and_melt_quotes(db: Database): -# # async with db.connect() as conn: -# # await conn.execute( -# # f"ALTER TABLE {db.table_with_schema('mint_quotes')} ADD COLUMN state TEXT" -# # ) -# # await conn.execute( -# # f"ALTER TABLE {db.table_with_schema('melt_quotes')} ADD COLUMN state TEXT" -# # ) - -# # # get all melt and mint quotes and figure out the state to set using the `paid` column -# # # and the `paid` and `issued` column respectively -# # # mint quotes: -# # async with db.connect() as conn: -# # rows = await conn.fetchall( -# # f"SELECT * FROM {db.table_with_schema('mint_quotes')}" -# # ) -# # for row in rows: -# # if row["issued"]: -# # state = "issued" -# # elif row["paid"]: -# # state = "paid" -# # else: -# # state = "unpaid" -# # await conn.execute( -# # f"UPDATE {db.table_with_schema('mint_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'" -# # ) - -# # # melt quotes: -# # async with db.connect() as conn: -# # rows = await conn.fetchall( -# # f"SELECT * FROM {db.table_with_schema('melt_quotes')}" -# # ) -# # for row in rows: -# # if row["paid"]: -# # state = "paid" -# # else: -# # state = "unpaid" -# # await conn.execute( -# # f"UPDATE {db.table_with_schema('melt_quotes')} SET state = '{state}' WHERE quote = '{row['quote']}'" -# # ) -# # add the equivalent of the above migration for the wallet here. do not use table_with_schema. use the tables and columns -# # as they are defined in the wallet db - - -# async def m020_add_state_to_mint_and_melt_quotes(db: Database): -# async with db.connect() as conn: -# await conn.execute("ALTER TABLE mint_quotes ADD COLUMN state TEXT") -# await conn.execute("ALTER TABLE melt_quotes ADD COLUMN state TEXT") - -# # get all melt and mint quotes and figure out the state to set using the `paid` column -# # and the `paid` and `issued` column respectively -# # mint quotes: -# async with db.connect() as conn: -# rows = await conn.fetchall("SELECT * FROM mint_quotes") -# for row in rows: -# if row["issued"]: -# state = "issued" -# elif row["paid"]: -# state = "paid" -# else: -# state = "unpaid" -# await conn.execute( -# f"UPDATE mint_quotes SET state = '{state}' WHERE quote = '{row['quote']}'" -# ) - -# # melt quotes: -# async with db.connect() as conn: -# rows = await conn.fetchall("SELECT * FROM melt_quotes") -# for row in rows: -# if row["paid"]: -# state = "paid" -# else: -# state = "unpaid" -# await conn.execute( -# f"UPDATE melt_quotes SET state = '{state}' WHERE quote = '{row['quote']}'" -# ) +async def m013_add_mint_and_melt_quote_tables(db: Database): + async with db.connect() as conn: + await conn.execute( + """ + CREATE TABLE IF NOT EXISTS bolt11_mint_quotes ( + quote TEXT PRIMARY KEY, + mint TEXT NOT NULL, + method TEXT NOT NULL, + request TEXT NOT NULL, + checking_id TEXT NOT NULL, + unit TEXT NOT NULL, + amount INTEGER NOT NULL, + state TEXT NOT NULL, + created_time INTEGER, + paid_time INTEGER, + expiry INTEGER + ); + """ + ) + + await conn.execute( + """ + CREATE TABLE IF NOT EXISTS bolt11_melt_quotes ( + quote TEXT PRIMARY KEY, + mint TEXT NOT NULL, + method TEXT NOT NULL, + request TEXT NOT NULL, + checking_id TEXT NOT NULL, + unit TEXT NOT NULL, + amount INTEGER NOT NULL, + fee_reserve INTEGER NOT NULL, + state TEXT NOT NULL, + created_time INTEGER, + paid_time INTEGER, + fee_paid INTEGER, + payment_preimage TEXT, + expiry INTEGER, + change TEXT + ); + """ + ) diff --git a/cashu/wallet/v1_api.py b/cashu/wallet/v1_api.py index 36dc20df..ba4d9c06 100644 --- a/cashu/wallet/v1_api.py +++ b/cashu/wallet/v1_api.py @@ -9,6 +9,8 @@ from loguru import logger from pydantic import ValidationError +from cashu.wallet.crud import get_bolt11_melt_quote + from ..core.base import ( BlindedMessage, BlindedSignature, @@ -45,9 +47,6 @@ ) from ..core.settings import settings from ..tor.tor import TorProxy -from .crud import ( - get_lightning_invoice, -) from .wallet_deprecated import LedgerAPIDeprecated @@ -476,10 +475,10 @@ def _meltrequest_include_fields( # BEGIN backwards compatibility < 0.15.0 # assume the mint has not upgraded yet if we get a 404 if resp.status_code == 404: - invoice = await get_lightning_invoice(id=quote, db=self.db) - assert invoice, f"no invoice found for id {quote}" + melt_quote = await get_bolt11_melt_quote(quote=quote, db=self.db) + assert melt_quote, f"no melt_quote found for id {quote}" ret: PostMeltResponse_deprecated = await self.melt_deprecated( - proofs=proofs, outputs=outputs, invoice=invoice.bolt11 + proofs=proofs, outputs=outputs, invoice=melt_quote.request ) elif isinstance(e, ValidationError): # BEGIN backwards compatibility < 0.16.0 diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index c6458a71..8d61e9e7 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -4,7 +4,6 @@ import time from typing import Callable, Dict, List, Optional, Tuple, Union -import bolt11 from bip32 import BIP32 from loguru import logger @@ -12,8 +11,10 @@ BlindedMessage, BlindedSignature, DLEQWallet, - Invoice, + MeltQuote, MeltQuoteState, + MintQuote, + MintQuoteState, Proof, Unit, WalletKeyset, @@ -26,6 +27,7 @@ from ..core.helpers import ( amount_summary, calculate_number_of_blank_outputs, + sum_promises, sum_proofs, ) from ..core.json_rpc.base import JSONRPCSubscriptionKinds @@ -45,11 +47,13 @@ invalidate_proof, secret_used, set_secret_derivation, + store_bolt11_melt_quote, + store_bolt11_mint_quote, store_keyset, - store_lightning_invoice, store_proof, + update_bolt11_melt_quote, + update_bolt11_mint_quote, update_keyset, - update_lightning_invoice, update_proof, ) from .htlc import WalletHTLC @@ -312,7 +316,9 @@ async def activate_keyset(self, keyset_id: Optional[str] = None) -> None: self.keyset_id = chosen_keyset.id - logger.debug(f"Activated keyset {self.keyset_id}") + logger.debug( + f"Activated keyset {self.keyset_id} ({self.keysets[self.keyset_id].unit}) fee: {self.keysets[self.keyset_id].input_fee_ppk}" + ) async def load_mint(self, keyset_id: str = "", force_old_keysets=False) -> None: """ @@ -381,8 +387,8 @@ async def _check_used_secrets(self, secrets): async def request_mint_with_callback( self, amount: int, callback: Callable, memo: Optional[str] = None - ) -> Tuple[Invoice, SubscriptionManager]: - """Request a Lightning invoice for minting tokens. + ) -> Tuple[MintQuote, SubscriptionManager]: + """Request a quote invoice for minting tokens. Args: amount (int): Amount for Lightning invoice in satoshis @@ -390,7 +396,7 @@ async def request_mint_with_callback( memo (Optional[str], optional): Memo for the Lightning invoice. Defaults Returns: - Invoice: Lightning invoice + MintQuote: Mint Quote """ mint_qoute = await super().mint_quote(amount, self.unit, memo) subscriptions = SubscriptionManager(self.url) @@ -402,21 +408,13 @@ async def request_mint_with_callback( filters=[mint_qoute.quote], callback=callback, ) - # return the invoice - decoded_invoice = bolt11.decode(mint_qoute.request) - invoice = Invoice( - amount=amount, - bolt11=mint_qoute.request, - payment_hash=decoded_invoice.payment_hash, - id=mint_qoute.quote, - out=False, - time_created=int(time.time()), - ) - await store_lightning_invoice(db=self.db, invoice=invoice) - return invoice, subscriptions + quote = MintQuote.from_resp_wallet(mint_qoute, self.url, amount, self.unit.name) + await store_bolt11_mint_quote(db=self.db, quote=quote) - async def request_mint(self, amount: int, memo: Optional[str] = None) -> Invoice: - """Request a Lightning invoice for minting tokens. + return quote, subscriptions + + async def request_mint(self, amount: int, memo: Optional[str] = None) -> MintQuote: + """Request a quote invoice for minting tokens. Args: amount (int): Amount for Lightning invoice in satoshis @@ -424,20 +422,14 @@ async def request_mint(self, amount: int, memo: Optional[str] = None) -> Invoice memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None. Returns: - PostMintQuoteResponse: Mint Quote Response + MintQuote: Mint Quote """ mint_quote_response = await super().mint_quote(amount, self.unit, memo) - decoded_invoice = bolt11.decode(mint_quote_response.request) - invoice = Invoice( - amount=amount, - bolt11=mint_quote_response.request, - payment_hash=decoded_invoice.payment_hash, - id=mint_quote_response.quote, - out=False, - time_created=int(time.time()), + quote = MintQuote.from_resp_wallet( + mint_quote_response, self.url, amount, self.unit.name ) - await store_lightning_invoice(db=self.db, invoice=invoice) - return invoice + await store_bolt11_mint_quote(db=self.db, quote=quote) + return quote def split_wallet_state(self, amount: int) -> List[int]: """This function produces an amount split for outputs based on the current state of the wallet. @@ -484,33 +476,10 @@ def split_wallet_state(self, amount: int) -> List[int]: return amounts - async def mint_quote(self, amount: int, memo: Optional[str] = None) -> Invoice: - """Request a Lightning invoice for minting tokens. - - Args: - amount (int): Amount for Lightning invoice in satoshis - memo (Optional[str], optional): Memo for the Lightning invoice. Defaults to None. - - Returns: - Invoice: Lightning invoice for minting tokens - """ - mint_quote_response = await super().mint_quote(amount, self.unit) - decoded_invoice = bolt11.decode(mint_quote_response.request) - invoice = Invoice( - amount=amount, - bolt11=mint_quote_response.request, - payment_hash=decoded_invoice.payment_hash, - id=mint_quote_response.quote, - out=False, - time_created=int(time.time()), - ) - await store_lightning_invoice(db=self.db, invoice=invoice) - return invoice - async def mint( self, amount: int, - id: str, + quote_id: str, split: Optional[List[int]] = None, ) -> List[Proof]: """Mint tokens of a specific amount after an invoice has been paid. @@ -553,7 +522,7 @@ async def mint( outputs, rs = self._construct_outputs(amounts, secrets, rs) # will raise exception if mint is unsuccessful - promises = await super().mint(outputs, id) + promises = await super().mint(outputs, quote_id) promises_keyset_id = promises[0].id await bump_secret_derivation( @@ -561,15 +530,17 @@ async def mint( ) proofs = await self._construct_proofs(promises, secrets, rs, derivation_paths) - if id: - await update_lightning_invoice( - db=self.db, id=id, paid=True, time_paid=int(time.time()) - ) - # store the mint_id in proofs - async with self.db.connect() as conn: - for p in proofs: - p.mint_id = id - await update_proof(p, mint_id=id, conn=conn) + await update_bolt11_mint_quote( + db=self.db, + quote=quote_id, + state=MintQuoteState.paid, + paid_time=int(time.time()), + ) + # store the mint_id in proofs + async with self.db.connect() as conn: + for p in proofs: + p.mint_id = quote_id + await update_proof(p, mint_id=quote_id, conn=conn) return proofs async def redeem( @@ -725,11 +696,19 @@ async def melt_quote( """ if amount and not self.mint_info.supports_mpp("bolt11", self.unit): raise Exception("Mint does not support MPP, cannot specify amount.") - melt_quote = await super().melt_quote(invoice, self.unit, amount) + melt_quote_resp = await super().melt_quote(invoice, self.unit, amount) logger.debug( - f"Mint wants {self.unit.str(melt_quote.fee_reserve)} as fee reserve." + f"Mint wants {self.unit.str(melt_quote_resp.fee_reserve)} as fee reserve." + ) + melt_quote = MeltQuote.from_resp_wallet( + melt_quote_resp, + self.url, + amount=melt_quote_resp.amount, + unit=self.unit.name, + request=invoice, ) - return melt_quote + await store_bolt11_melt_quote(db=self.db, quote=melt_quote) + return melt_quote_resp async def melt( self, proofs: List[Proof], invoice: str, fee_reserve_sat: int, quote_id: str @@ -744,6 +723,7 @@ async def melt( """ # Make sure we're operating on an independent copy of proofs proofs = copy.copy(proofs) + amount = sum_proofs(proofs) # Generate a number of blank outputs for any overpaid fees. As described in # NUT-08, the mint will imprint these outputs with a value depending on the @@ -764,59 +744,56 @@ async def melt( p.melt_id = quote_id await update_proof(p, melt_id=quote_id, conn=conn) - # we store the invoice object in the database to later be able to check the invoice state - - decoded_invoice = bolt11.decode(invoice) - invoice_obj = Invoice( - amount=-sum_proofs(proofs), - bolt11=invoice, - payment_hash=decoded_invoice.payment_hash, - # preimage=status.preimage, - paid=False, - time_paid=int(time.time()), - id=quote_id, # store the same ID in the invoice - out=True, # outgoing invoice + melt_quote_resp = await super().melt(quote_id, proofs, change_outputs) + melt_quote = MeltQuote.from_resp_wallet( + melt_quote_resp, + self.url, + amount=amount, + unit=self.unit.name, + request=invoice, ) - # store invoice in db as not paid yet - await store_lightning_invoice(db=self.db, invoice=invoice_obj) - - status = await super().melt(quote_id, proofs, change_outputs) - # if payment fails - if MeltQuoteState(status.state) == MeltQuoteState.unpaid: + if melt_quote.state == MeltQuoteState.unpaid: # remove the melt_id in proofs and set reserved to False for p in proofs: p.melt_id = None p.reserved = False await update_proof(p, melt_id="", db=self.db) raise Exception("could not pay invoice.") - elif MeltQuoteState(status.state) == MeltQuoteState.pending: + elif melt_quote.state == MeltQuoteState.pending: # payment is still pending - return status + logger.debug("Payment is still pending.") + return melt_quote_resp # invoice was paid successfully await self.invalidate(proofs) # update paid status in db logger.trace(f"Settings invoice {quote_id} to paid.") - await update_lightning_invoice( + logger.trace(f"Quote: {melt_quote_resp}") + fee_paid = melt_quote.amount + melt_quote.fee_paid + if melt_quote.change: + fee_paid -= sum_promises(melt_quote.change) + + await update_bolt11_melt_quote( db=self.db, - id=quote_id, - paid=True, - time_paid=int(time.time()), - preimage=status.payment_preimage, + quote=quote_id, + state=MeltQuoteState.paid, + paid_time=int(time.time()), + payment_preimage=melt_quote.payment_preimage or "", + fee_paid=fee_paid, ) # handle change and produce proofs - if status.change: + if melt_quote.change: change_proofs = await self._construct_proofs( - status.change, - change_secrets[: len(status.change)], - change_rs[: len(status.change)], - change_derivation_paths[: len(status.change)], + melt_quote.change, + change_secrets[: len(melt_quote.change)], + change_rs[: len(melt_quote.change)], + change_derivation_paths[: len(melt_quote.change)], ) logger.debug(f"Received change: {self.unit.str(sum_proofs(change_proofs))}") - return status + return melt_quote_resp async def check_proof_state(self, proofs) -> PostCheckStateResponse: return await super().check_proof_state(proofs) diff --git a/tests/test_db.py b/tests/test_db.py index fca93b6f..a9699ab1 100644 --- a/tests/test_db.py +++ b/tests/test_db.py @@ -63,7 +63,7 @@ async def test_db_tables(ledger: Ledger): "SELECT table_name FROM information_schema.tables WHERE table_schema =" " 'public';" ) - tables_all: List[Tuple[str]] = tables_res.all() + tables_all: List[Tuple[str]] = tables_res.all() # type: ignore tables = [t[0] for t in tables_all] tables_expected = [ "dbversions", @@ -117,7 +117,7 @@ async def test_db_get_connection(ledger: Ledger): # @pytest.mark.asyncio # async def test_db_get_connection_locked(wallet: Wallet, ledger: Ledger): -# invoice = await wallet.request_mint(64) +# mint_quote = await wallet.request_mint(64) # async def get_connection(): # """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)""" @@ -129,7 +129,7 @@ async def test_db_get_connection(ledger: Ledger): # ) as conn2: # # write something with conn1, we never reach this point if the lock works # await conn2.execute( -# f"INSERT INTO mint_quotes (quote, amount) VALUES ('{invoice.id}', 100);" +# f"INSERT INTO mint_quotes (quote, amount) VALUES ('{mint_quote.quote}', 100);" # ) # except Exception as exc: # # this is expected to raise @@ -149,28 +149,28 @@ async def test_db_get_connection_lock_row(wallet: Wallet, ledger: Ledger): if ledger.db.type == db.SQLITE: pytest.skip("SQLite does not support row locking") - invoice = await wallet.request_mint(64) + mint_quote = await wallet.request_mint(64) async def get_connection(): """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)""" try: async with ledger.db.get_connection( lock_table="mint_quotes", - lock_select_statement=f"quote='{invoice.id}'", + lock_select_statement=f"quote='{mint_quote.quote}'", lock_timeout=0.1, ) as conn1: await conn1.execute( - f"UPDATE mint_quotes SET amount=100 WHERE quote='{invoice.id}';" + f"UPDATE mint_quotes SET amount=100 WHERE quote='{mint_quote.quote}';" ) try: async with ledger.db.get_connection( lock_table="mint_quotes", - lock_select_statement=f"quote='{invoice.id}'", + lock_select_statement=f"quote='{mint_quote.quote}'", lock_timeout=0.1, ) as conn2: # write something with conn1, we never reach this point if the lock works await conn2.execute( - f"UPDATE mint_quotes SET amount=101 WHERE quote='{invoice.id}';" + f"UPDATE mint_quotes SET amount=101 WHERE quote='{mint_quote.quote}';" ) except Exception as exc: # this is expected to raise @@ -189,9 +189,9 @@ async def test_db_verify_spent_proofs_and_set_pending_race_condition( wallet: Wallet, ledger: Ledger ): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 await assert_err_multiple( @@ -211,9 +211,9 @@ async def test_db_verify_spent_proofs_and_set_pending_delayed_no_race_condition( wallet: Wallet, ledger: Ledger ): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 async def delayed_verify_spent_proofs_and_set_pending(): @@ -234,9 +234,9 @@ async def test_db_verify_spent_proofs_and_set_pending_no_race_condition_differen wallet: Wallet, ledger: Ledger ): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id, split=[32, 32]) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote, split=[32, 32]) assert wallet.balance == 64 assert len(wallet.proofs) == 2 @@ -251,26 +251,26 @@ async def test_db_get_connection_lock_different_row(wallet: Wallet, ledger: Ledg if ledger.db.type == db.SQLITE: pytest.skip("SQLite does not support row locking") # this should work since we lock two different rows - invoice = await wallet.request_mint(64) - invoice2 = await wallet.request_mint(64) + mint_quote = await wallet.request_mint(64) + mint_quote_2 = await wallet.request_mint(64) async def get_connection2(): """This code makes sure that only the error of the second connection is raised (which we check in the assert_err)""" try: async with ledger.db.get_connection( lock_table="mint_quotes", - lock_select_statement=f"quote='{invoice.id}'", + lock_select_statement=f"quote='{mint_quote.quote}'", lock_timeout=0.1, ): try: async with ledger.db.get_connection( lock_table="mint_quotes", - lock_select_statement=f"quote='{invoice2.id}'", + lock_select_statement=f"quote='{mint_quote_2.quote}'", lock_timeout=0.1, ) as conn2: # write something with conn1, this time we should reach this block with postgres quote = await ledger.crud.get_mint_quote( - quote_id=invoice2.id, db=ledger.db, conn=conn2 + quote_id=mint_quote_2.quote, db=ledger.db, conn=conn2 ) assert quote is not None quote.amount = 100 @@ -294,10 +294,10 @@ async def get_connection2(): @pytest.mark.asyncio async def test_db_lock_table(wallet: Wallet, ledger: Ledger): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) - await wallet.mint(64, id=invoice.id) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 async with ledger.db.connect(lock_table="proofs_pending", lock_timeout=0.1) as conn: diff --git a/tests/test_mint_api.py b/tests/test_mint_api.py index fe38bc70..4d9f058f 100644 --- a/tests/test_mint_api.py +++ b/tests/test_mint_api.py @@ -159,9 +159,9 @@ async def test_api_keyset_keys_old_keyset_id(ledger: Ledger): reason="settings.debug_mint_only_deprecated is set", ) async def test_split(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 secrets, rs, derivation_paths = await wallet.generate_n_secrets(2) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) @@ -240,15 +240,14 @@ async def test_mint_quote(ledger: Ledger): reason="settings.debug_mint_only_deprecated is set", ) async def test_mint(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - quote_id = invoice.id + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) outputs_payload = [o.dict() for o in outputs] response = httpx.post( f"{BASE_URL}/v1/mint/bolt11", - json={"quote": quote_id, "outputs": outputs_payload}, + json={"quote": mint_quote.quote, "outputs": outputs_payload}, timeout=None, ) assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -273,8 +272,8 @@ async def test_mint(ledger: Ledger, wallet: Wallet): ) async def test_melt_quote_internal(ledger: Ledger, wallet: Wallet): # internal invoice - invoice = await wallet.request_mint(64) - request = invoice.bolt11 + mint_quote = await wallet.request_mint(64) + request = mint_quote.request response = httpx.post( f"{BASE_URL}/v1/melt/quote/bolt11", json={"unit": "sat", "request": request}, @@ -358,14 +357,14 @@ async def test_melt_quote_external(ledger: Ledger, wallet: Wallet): ) async def test_melt_internal(ledger: Ledger, wallet: Wallet): # internal invoice - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create invoice to melt to - invoice = await wallet.request_mint(64) - invoice_payment_request = invoice.bolt11 + mint_quote = await wallet.request_mint(64) + invoice_payment_request = mint_quote.request quote = await wallet.melt_quote(invoice_payment_request) assert quote.amount == 64 @@ -389,7 +388,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): ) assert response.status_code == 200, f"{response.url} {response.status_code}" result = response.json() - assert result.get("payment_preimage") is not None + assert result.get("payment_preimage") is None assert result["paid"] is True # deserialize the response @@ -397,7 +396,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): assert resp_quote.quote == quote.quote # internal invoice, no preimage, no change - assert resp_quote.payment_preimage == "" + assert resp_quote.payment_preimage is None assert resp_quote.change == [] assert resp_quote.state == MeltQuoteState.paid.value @@ -417,9 +416,9 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): ) async def test_melt_external(ledger: Ledger, wallet: Wallet): # internal invoice - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 invoice_dict = get_real_invoice(62) @@ -493,9 +492,9 @@ async def test_api_check_state(ledger: Ledger): reason="settings.debug_mint_only_deprecated is set", ) async def test_api_restore(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 secret_counter = await bump_secret_derivation( db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True diff --git a/tests/test_mint_api_deprecated.py b/tests/test_mint_api_deprecated.py index 226af28a..bf829e76 100644 --- a/tests/test_mint_api_deprecated.py +++ b/tests/test_mint_api_deprecated.py @@ -67,9 +67,9 @@ async def test_api_keyset_keys(ledger: Ledger): @pytest.mark.asyncio async def test_split(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(20000, 20001) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) @@ -88,9 +88,9 @@ async def test_split(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio async def test_split_deprecated_with_amount(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(80000, 80001) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) @@ -124,16 +124,15 @@ async def test_api_mint_validation(ledger): @pytest.mark.asyncio async def test_mint(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - quote_id = invoice.id + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) secrets, rs, derivation_paths = await wallet.generate_secrets_from_to(10000, 10001) outputs, rs = wallet._construct_outputs([32, 32], secrets, rs) outputs_payload = [o.dict() for o in outputs] response = httpx.post( f"{BASE_URL}/mint", json={"outputs": outputs_payload}, - params={"hash": quote_id}, + params={"hash": mint_quote.quote}, timeout=None, ) assert response.status_code == 200, f"{response.url} {response.status_code}" @@ -150,15 +149,15 @@ async def test_mint(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio async def test_melt_internal(ledger: Ledger, wallet: Wallet): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create invoice to melt to - invoice = await wallet.request_mint(64) + mint_quote = await wallet.request_mint(64) - invoice_payment_request = invoice.bolt11 + invoice_payment_request = mint_quote.request quote = await wallet.melt_quote(invoice_payment_request) assert quote.amount == 64 @@ -182,7 +181,7 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): ) assert response.status_code == 200, f"{response.url} {response.status_code}" result = response.json() - assert result.get("preimage") is not None + assert result.get("preimage") is None assert result["paid"] is True @@ -190,14 +189,14 @@ async def test_melt_internal(ledger: Ledger, wallet: Wallet): async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet): # Clients without NUT-08 will not send change outputs # internal invoice - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create invoice to melt to - invoice = await wallet.request_mint(64) - invoice_payment_request = invoice.bolt11 + mint_quote = await wallet.request_mint(64) + invoice_payment_request = mint_quote.request quote = await wallet.melt_quote(invoice_payment_request) assert quote.amount == 64 assert quote.fee_reserve == 0 @@ -218,7 +217,7 @@ async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet): ) assert response.status_code == 200, f"{response.url} {response.status_code}" result = response.json() - assert result.get("preimage") is not None + assert result.get("preimage") is None assert result["paid"] is True @@ -229,9 +228,9 @@ async def test_melt_internal_no_change_outputs(ledger: Ledger, wallet: Wallet): ) async def test_melt_external(ledger: Ledger, wallet: Wallet): # internal invoice - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create invoice to melt to @@ -271,11 +270,11 @@ async def test_melt_external(ledger: Ledger, wallet: Wallet): @pytest.mark.asyncio async def test_checkfees(ledger: Ledger, wallet: Wallet): # internal invoice - invoice = await wallet.request_mint(64) + mint_quote = await wallet.request_mint(64) response = httpx.post( f"{BASE_URL}/checkfees", json={ - "pr": invoice.bolt11, + "pr": mint_quote.request, }, timeout=None, ) @@ -323,9 +322,9 @@ async def test_api_check_state(ledger: Ledger): @pytest.mark.asyncio async def test_api_restore(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 secret_counter = await bump_secret_derivation( db=wallet.db, keyset_id=wallet.keyset_id, by=0, skip=True diff --git a/tests/test_mint_db.py b/tests/test_mint_db.py index 6c9864f9..1d04fb78 100644 --- a/tests/test_mint_db.py +++ b/tests/test_mint_db.py @@ -37,9 +37,9 @@ async def wallet(ledger: Ledger): @pytest.mark.asyncio @pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS") async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) proofs = wallet.proofs.copy() proofs_states_before_split = await wallet.check_proof_state(proofs) @@ -61,26 +61,21 @@ async def test_mint_proofs_pending(wallet: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_mint_quote(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) + mint_quote = await wallet.request_mint(128) + quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None - assert quote.quote == invoice.id assert quote.amount == 128 assert quote.unit == "sat" assert not quote.paid - assert quote.checking_id == invoice.payment_hash # assert quote.paid_time is None assert quote.created_time @pytest.mark.asyncio async def test_mint_quote_state_transitions(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) + mint_quote = await wallet.request_mint(128) + quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None - assert quote.quote == invoice.id assert quote.unpaid # set pending again @@ -129,11 +124,9 @@ async def set_state(quote, state): @pytest.mark.asyncio async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None - quote = await ledger.crud.get_mint_quote(request=invoice.bolt11, db=ledger.db) + mint_quote = await wallet.request_mint(128) + quote = await ledger.crud.get_mint_quote(request=mint_quote.request, db=ledger.db) assert quote is not None - assert quote.quote == invoice.id assert quote.amount == 128 assert quote.unit == "sat" assert not quote.paid @@ -143,10 +136,9 @@ async def test_get_mint_quote_by_request(wallet: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_melt_quote(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None + mint_quote = await wallet.request_mint(128) melt_quote = await ledger.melt_quote( - PostMeltQuoteRequest(request=invoice.bolt11, unit="sat") + PostMeltQuoteRequest(request=mint_quote.request, unit="sat") ) quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db) assert quote is not None @@ -154,17 +146,15 @@ async def test_melt_quote(wallet: Wallet, ledger: Ledger): assert quote.amount == 128 assert quote.unit == "sat" assert not quote.paid - assert quote.checking_id == invoice.payment_hash # assert quote.paid_time is None assert quote.created_time @pytest.mark.asyncio async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None + mint_quote = await wallet.request_mint(128) melt_quote = await ledger.melt_quote( - PostMeltQuoteRequest(request=invoice.bolt11, unit="sat") + PostMeltQuoteRequest(request=mint_quote.request, unit="sat") ) assert melt_quote is not None assert melt_quote.state == MeltQuoteState.unpaid.value @@ -187,10 +177,9 @@ async def test_melt_quote_set_pending(wallet: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_melt_quote_state_transitions(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None + mint_quote = await wallet.request_mint(128) melt_quote = await ledger.melt_quote( - PostMeltQuoteRequest(request=invoice.bolt11, unit="sat") + PostMeltQuoteRequest(request=mint_quote.request, unit="sat") ) quote = await ledger.crud.get_melt_quote(quote_id=melt_quote.quote, db=ledger.db) assert quote is not None @@ -218,33 +207,36 @@ async def set_state(quote, state): @pytest.mark.asyncio async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) - assert quote is not None - assert quote.unpaid + mint_quote = await wallet.request_mint(128) + mint_quote = await ledger.crud.get_mint_quote( + quote_id=mint_quote.quote, db=ledger.db + ) + assert mint_quote is not None + assert mint_quote.unpaid # pay_if_regtest pays on regtest, get_mint_quote pays on FakeWallet - await pay_if_regtest(invoice.bolt11) - _ = await ledger.get_mint_quote(invoice.id) + await pay_if_regtest(mint_quote.request) + _ = await ledger.get_mint_quote(mint_quote.quote) - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) + quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None assert quote.paid previous_state = MintQuoteState.paid await ledger.db_write._set_mint_quote_pending(quote.quote) - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) + quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None assert quote.pending # try to mint while pending - await assert_err(wallet.mint(128, id=invoice.id), "Mint quote already pending.") + await assert_err( + wallet.mint(128, quote_id=mint_quote.quote), "Mint quote already pending." + ) # set unpending await ledger.db_write._unset_mint_quote_pending(quote.quote, previous_state) - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) + quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None assert quote.state == previous_state assert quote.paid @@ -253,20 +245,19 @@ async def test_mint_quote_set_pending(wallet: Wallet, ledger: Ledger): # quote.state = MintQuoteState.paid # await ledger.crud.update_mint_quote(quote=quote, db=ledger.db) - await wallet.mint(quote.amount, id=quote.quote) + await wallet.mint(quote.amount, quote_id=quote.quote) # check if quote is issued - quote = await ledger.crud.get_mint_quote(quote_id=invoice.id, db=ledger.db) + quote = await ledger.crud.get_mint_quote(quote_id=mint_quote.quote, db=ledger.db) assert quote is not None assert quote.issued @pytest.mark.asyncio async def test_db_events_add_client(wallet: Wallet, ledger: Ledger): - invoice = await wallet.request_mint(128) - assert invoice is not None + mint_quote = await wallet.request_mint(128) melt_quote = await ledger.melt_quote( - PostMeltQuoteRequest(request=invoice.bolt11, unit="sat") + PostMeltQuoteRequest(request=mint_quote.request, unit="sat") ) assert melt_quote is not None assert melt_quote.state == MeltQuoteState.unpaid.value diff --git a/tests/test_mint_fees.py b/tests/test_mint_fees.py index 529d3f5b..22617f7d 100644 --- a/tests/test_mint_fees.py +++ b/tests/test_mint_fees.py @@ -48,9 +48,9 @@ def set_ledger_keyset_fees( @pytest.mark.asyncio async def test_get_fees_for_proofs(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, split=[1] * 64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, split=[1] * 64, quote_id=mint_quote.quote) # two proofs @@ -105,9 +105,9 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger): for keyset in wallet1.keysets.values(): assert keyset.input_fee_ppk == 100 - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) assert sum_proofs(send_proofs) == 10 @@ -123,9 +123,11 @@ async def test_wallet_selection_with_fee(wallet1: Wallet, ledger: Ledger): async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger): # set fees to 100 ppk set_ledger_keyset_fees(100, ledger, wallet1) - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id, split=[32, 32]) # make sure we need to swap + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint( + 64, quote_id=mint_quote.quote, split=[32, 32] + ) # make sure we need to swap # quirk: this should call a `/v1/swap` with the mint but the mint will # throw an error since the fees are only changed in the `ledger` instance, not in the uvicorn API server @@ -142,9 +144,9 @@ async def test_wallet_swap_to_send_with_fee(wallet1: Wallet, ledger: Ledger): async def test_split_with_fees(wallet1: Wallet, ledger: Ledger): # set fees to 100 ppk set_ledger_keyset_fees(100, ledger) - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) fees = ledger.get_fees_for_proofs(send_proofs) @@ -160,9 +162,9 @@ async def test_split_with_fees(wallet1: Wallet, ledger: Ledger): async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger): # set fees to 100 ppk set_ledger_keyset_fees(1234, ledger) - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) fees = ledger.get_fees_for_proofs(send_proofs) @@ -178,9 +180,9 @@ async def test_split_with_high_fees(wallet1: Wallet, ledger: Ledger): async def test_split_not_enough_fees(wallet1: Wallet, ledger: Ledger): # set fees to 100 ppk set_ledger_keyset_fees(100, ledger) - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) send_proofs, _ = await wallet1.select_to_send(wallet1.proofs, 10) fees = ledger.get_fees_for_proofs(send_proofs) @@ -200,14 +202,14 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger): set_ledger_keyset_fees(100, ledger, wallet1) # mint twice so we have enough to pay the second invoice back - invoice = await wallet1.request_mint(128) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(128, id=invoice.id) + mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(128, quote_id=mint_quote.quote) assert wallet1.balance == 128 # create a mint quote so that we can melt to it internally invoice_to_pay = await wallet1.request_mint(64) - invoice_payment_request = invoice_to_pay.bolt11 + invoice_payment_request = invoice_to_pay.request melt_quote = await ledger.melt_quote( PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") @@ -247,9 +249,9 @@ async def test_melt_external_with_fees(wallet1: Wallet, ledger: Ledger): set_ledger_keyset_fees(100, ledger, wallet1) # mint twice so we have enough to pay the second invoice back - invoice = await wallet1.request_mint(128) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(128, id=invoice.id) + mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(128, quote_id=mint_quote.quote) assert wallet1.balance == 128 invoice_dict = get_real_invoice(64) diff --git a/tests/test_mint_init.py b/tests/test_mint_init.py index 60817fe3..3568dcb9 100644 --- a/tests/test_mint_init.py +++ b/tests/test_mint_init.py @@ -261,9 +261,9 @@ async def test_startup_fakewallet_pending_quote_unknown(ledger: Ledger): @pytest.mark.skipif(is_fake, reason="only regtest") async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Ledger): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice @@ -305,9 +305,9 @@ async def test_startup_regtest_pending_quote_pending(wallet: Wallet, ledger: Led @pytest.mark.skipif(is_fake, reason="only regtest") async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Ledger): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice @@ -353,9 +353,9 @@ async def test_startup_regtest_pending_quote_success(wallet: Wallet, ledger: Led async def test_startup_regtest_pending_quote_failure(wallet: Wallet, ledger: Ledger): """Simulate a failure to pay the hodl invoice by canceling it.""" # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice @@ -407,9 +407,9 @@ async def test_startup_regtest_pending_quote_unknown(wallet: Wallet, ledger: Led points to an unknown payment.""" # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice diff --git a/tests/test_mint_melt.py b/tests/test_mint_melt.py index c135992f..f4460599 100644 --- a/tests/test_mint_melt.py +++ b/tests/test_mint_melt.py @@ -185,9 +185,9 @@ async def test_fakewallet_pending_quote_get_melt_quote_unknown(ledger: Ledger): @pytest.mark.asyncio @pytest.mark.skipif(is_regtest, reason="only fake wallet") async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid + await wallet.mint(64, quote_id=mint_quote.quote) # invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" quote_id = ( @@ -205,9 +205,9 @@ async def test_melt_lightning_pay_invoice_settled(ledger: Ledger, wallet: Wallet @pytest.mark.asyncio @pytest.mark.skipif(is_regtest, reason="only fake wallet") async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet: Wallet): - invoice = await wallet.request_mint(64) - await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid + await wallet.mint(64, quote_id=mint_quote.quote) # invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" quote_id = ( @@ -254,9 +254,9 @@ async def test_melt_lightning_pay_invoice_failed_failed(ledger: Ledger, wallet: async def test_melt_lightning_pay_invoice_failed_settled( ledger: Ledger, wallet: Wallet ): - invoice = await wallet.request_mint(64) - await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid + await wallet.mint(64, quote_id=mint_quote.quote) invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" quote_id = ( await ledger.melt_quote( @@ -278,9 +278,9 @@ async def test_melt_lightning_pay_invoice_failed_settled( async def test_melt_lightning_pay_invoice_failed_pending( ledger: Ledger, wallet: Wallet ): - invoice = await wallet.request_mint(64) - await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid + await wallet.mint(64, quote_id=mint_quote.quote) invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" quote_id = ( await ledger.melt_quote( @@ -303,9 +303,9 @@ async def test_melt_lightning_pay_invoice_exception_exception( ledger: Ledger, wallet: Wallet ): """Simulates the case where pay_invoice and get_payment_status raise an exception (due to network issues for example).""" - invoice = await wallet.request_mint(64) - await ledger.get_mint_quote(invoice.id) # fakewallet: set the quote to paid - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await ledger.get_mint_quote(mint_quote.quote) # fakewallet: set the quote to paid + await wallet.mint(64, quote_id=mint_quote.quote) # invoice_64_sat = "lnbcrt640n1pn0r3tfpp5e30xac756gvd26cn3tgsh8ug6ct555zrvl7vsnma5cwp4g7auq5qdqqcqzzsxqyz5vqsp5xfhtzg0y3mekv6nsdnj43c346smh036t4f8gcfa2zwpxzwcryqvs9qxpqysgqw5juev8y3zxpdu0mvdrced5c6a852f9x7uh57g6fgjgcg5muqzd5474d7xgh770frazel67eejfwelnyr507q46hxqehala880rhlqspw07ta0" invoice_62_sat = "lnbcrt620n1pn0r3vepp5zljn7g09fsyeahl4rnhuy0xax2puhua5r3gspt7ttlfrley6valqdqqcqzzsxqyz5vqsp577h763sel3q06tfnfe75kvwn5pxn344sd5vnays65f9wfgx4fpzq9qxpqysgqg3re9afz9rwwalytec04pdhf9mvh3e2k4r877tw7dr4g0fvzf9sny5nlfggdy6nduy2dytn06w50ls34qfldgsj37x0ymxam0a687mspp0ytr8" quote_id = ( @@ -338,8 +338,8 @@ async def test_melt_lightning_pay_invoice_exception_exception( async def test_mint_melt_different_units(ledger: Ledger, wallet: Wallet): """Mint and melt different units.""" # load the wallet - invoice = await wallet.request_mint(64) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await wallet.mint(64, quote_id=mint_quote.quote) amount = 32 diff --git a/tests/test_mint_operations.py b/tests/test_mint_operations.py index ab457759..6859e768 100644 --- a/tests/test_mint_operations.py +++ b/tests/test_mint_operations.py @@ -38,14 +38,14 @@ async def wallet1(ledger: Ledger): @pytest.mark.skipif(is_regtest, reason="only works with FakeWallet") async def test_melt_internal(wallet1: Wallet, ledger: Ledger): # mint twice so we have enough to pay the second invoice back - invoice = await wallet1.request_mint(128) - await ledger.get_mint_quote(invoice.id) - await wallet1.mint(128, id=invoice.id) + mint_quote = await wallet1.request_mint(128) + await ledger.get_mint_quote(mint_quote.quote) + await wallet1.mint(128, quote_id=mint_quote.quote) assert wallet1.balance == 128 # create a mint quote so that we can melt to it internally - invoice_to_pay = await wallet1.request_mint(64) - invoice_payment_request = invoice_to_pay.bolt11 + mint_quote_to_pay = await wallet1.request_mint(64) + invoice_payment_request = mint_quote_to_pay.request melt_quote = await ledger.melt_quote( PostMeltQuoteRequest(request=invoice_payment_request, unit="sat") @@ -79,9 +79,9 @@ async def test_melt_internal(wallet1: Wallet, ledger: Ledger): @pytest.mark.skipif(is_fake, reason="only works with Regtest") async def test_melt_external(wallet1: Wallet, ledger: Ledger): # mint twice so we have enough to pay the second invoice back - invoice = await wallet1.request_mint(128) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(128, id=invoice.id) + mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(128, quote_id=mint_quote.quote) assert wallet1.balance == 128 invoice_dict = get_real_invoice(64) @@ -119,14 +119,14 @@ async def test_melt_external(wallet1: Wallet, ledger: Ledger): @pytest.mark.asyncio @pytest.mark.skipif(is_regtest, reason="only works with FakeWallet") async def test_mint_internal(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(128) - await ledger.get_mint_quote(invoice.id) - mint_quote = await ledger.get_mint_quote(invoice.id) + mint_quote = await wallet1.request_mint(128) + await ledger.get_mint_quote(mint_quote.quote) + mint_quote = await ledger.get_mint_quote(mint_quote.quote) assert mint_quote.paid, "mint quote should be paid" if not settings.debug_mint_only_deprecated: - mint_quote_resp = await wallet1.get_mint_quote(invoice.id) + mint_quote_resp = await wallet1.get_mint_quote(mint_quote.quote) assert ( mint_quote_resp.state == MeltQuoteState.paid.value ), "mint quote should be paid" @@ -136,14 +136,14 @@ async def test_mint_internal(wallet1: Wallet, ledger: Ledger): len(output_amounts) ) outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs) - await ledger.mint(outputs=outputs, quote_id=invoice.id) + await ledger.mint(outputs=outputs, quote_id=mint_quote.quote) await assert_err( - ledger.mint(outputs=outputs, quote_id=invoice.id), + ledger.mint(outputs=outputs, quote_id=mint_quote.quote), "outputs have already been signed before.", ) - mint_quote_after_payment = await ledger.get_mint_quote(invoice.id) + mint_quote_after_payment = await ledger.get_mint_quote(mint_quote.quote) assert mint_quote_after_payment.issued, "mint quote should be issued" assert mint_quote_after_payment.issued @@ -164,7 +164,7 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger): assert not mint_quote_resp.paid, "mint quote should not be paid" await assert_err( - wallet1.mint(128, id=quote.quote), + wallet1.mint(128, quote_id=quote.quote), "quote not paid", ) @@ -187,9 +187,9 @@ async def test_mint_external(wallet1: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_split(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10) secrets, rs, derivation_paths = await wallet1.generate_n_secrets(len(send_proofs)) @@ -204,9 +204,9 @@ async def test_split(wallet1: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) _, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10, set_reserved=False) await assert_err( ledger.swap(proofs=send_proofs, outputs=[]), @@ -216,9 +216,9 @@ async def test_split_with_no_outputs(wallet1: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) keep_proofs, send_proofs = await wallet1.swap_to_send( wallet1.proofs, 10, set_reserved=False @@ -245,9 +245,9 @@ async def test_split_with_input_less_than_outputs(wallet1: Wallet, ledger: Ledge @pytest.mark.asyncio async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(128) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(128, id=invoice.id) + mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(128, quote_id=mint_quote.quote) inputs = wallet1.proofs @@ -269,9 +269,9 @@ async def test_split_with_input_more_than_outputs(wallet1: Wallet, ledger: Ledge @pytest.mark.asyncio async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(128) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(128, split=[64, 64], id=invoice.id) + mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(128, split=[64, 64], quote_id=mint_quote.quote) inputs1 = wallet1.proofs[:1] inputs2 = wallet1.proofs[1:] @@ -304,30 +304,30 @@ async def test_split_twice_with_same_outputs(wallet1: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_mint_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(128) - await pay_if_regtest(invoice.bolt11) + mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote.request) output_amounts = [128] secrets, rs, derivation_paths = await wallet1.generate_n_secrets( len(output_amounts) ) outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs) - await ledger.mint(outputs=outputs, quote_id=invoice.id) + await ledger.mint(outputs=outputs, quote_id=mint_quote.quote) # now try to mint with the same outputs again - invoice2 = await wallet1.request_mint(128) - await pay_if_regtest(invoice2.bolt11) + mint_quote_2 = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote_2.request) await assert_err( - ledger.mint(outputs=outputs, quote_id=invoice2.id), + ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote), "outputs have already been signed before.", ) @pytest.mark.asyncio async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(130) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(130, id=invoice.id) + mint_quote = await wallet1.request_mint(130) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(130, quote_id=mint_quote.quote) output_amounts = [128] secrets, rs, derivation_paths = await wallet1.generate_n_secrets( @@ -336,9 +336,9 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger): outputs, rs = wallet1._construct_outputs(output_amounts, secrets, rs) # we use the outputs once for minting - invoice2 = await wallet1.request_mint(128) - await pay_if_regtest(invoice2.bolt11) - await ledger.mint(outputs=outputs, quote_id=invoice2.id) + mint_quote_2 = await wallet1.request_mint(128) + await pay_if_regtest(mint_quote_2.request) + await ledger.mint(outputs=outputs, quote_id=mint_quote_2.quote) # use the same outputs for melting mint_quote = await ledger.mint_quote(PostMintQuoteRequest(unit="sat", amount=128)) @@ -353,9 +353,9 @@ async def test_melt_with_same_outputs_twice(wallet1: Wallet, ledger: Ledger): @pytest.mark.asyncio async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(32) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(32, id=invoice.id) + mint_quote = await wallet1.request_mint(32) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(32, quote_id=mint_quote.quote) # outputs for fee return output_amounts = [1, 1, 1, 1] @@ -382,9 +382,9 @@ async def test_melt_with_less_inputs_than_invoice(wallet1: Wallet, ledger: Ledge @pytest.mark.asyncio async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(130) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(130, split=[64, 64, 2], id=invoice.id) + mint_quote = await wallet1.request_mint(130) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(130, split=[64, 64, 2], quote_id=mint_quote.quote) # outputs for fee return output_amounts = [1, 1, 1, 1] @@ -414,9 +414,9 @@ async def test_melt_with_more_inputs_than_invoice(wallet1: Wallet, ledger: Ledge @pytest.mark.asyncio async def test_check_proof_state(wallet1: Wallet, ledger: Ledger): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) keep_proofs, send_proofs = await wallet1.swap_to_send(wallet1.proofs, 10) @@ -427,13 +427,13 @@ async def test_check_proof_state(wallet1: Wallet, ledger: Ledger): # TODO: test keeps running forever, needs to be fixed # @pytest.mark.asyncio # async def test_websocket_quote_updates(wallet1: Wallet, ledger: Ledger): -# invoice = await wallet1.request_mint(64) +# mint_quote = await wallet1.request_mint(64) # ws = websocket.create_connection( # f"ws://localhost:{SERVER_PORT}/v1/quote/{invoice.id}" # ) # await asyncio.sleep(0.1) -# await pay_if_regtest(invoice.bolt11) -# await wallet1.mint(64, id=invoice.id) +# await pay_if_regtest(mint_quote.request) +# await wallet1.mint(64, quote_id=mint_quote.quote) # await asyncio.sleep(0.1) # data = str(ws.recv()) # ws.close() diff --git a/tests/test_mint_regtest.py b/tests/test_mint_regtest.py index a37332ab..17d2fec0 100644 --- a/tests/test_mint_regtest.py +++ b/tests/test_mint_regtest.py @@ -274,9 +274,9 @@ async def pay(): @pytest.mark.skipif(is_fake, reason="only regtest") async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 86963172..886ce73f 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -8,7 +8,12 @@ from cashu.core.errors import CashuError, KeysetNotFoundError from cashu.core.helpers import sum_proofs from cashu.core.settings import settings -from cashu.wallet.crud import get_keysets, get_lightning_invoice, get_proofs +from cashu.wallet.crud import ( + get_bolt11_melt_quote, + get_bolt11_mint_quote, + get_keysets, + get_proofs, +) from cashu.wallet.wallet import Wallet from cashu.wallet.wallet import Wallet as Wallet1 from cashu.wallet.wallet import Wallet as Wallet2 @@ -160,44 +165,41 @@ async def test_get_keysets(wallet1: Wallet): @pytest.mark.asyncio async def test_request_mint(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - assert invoice.payment_hash + mint_quote = await wallet1.request_mint(64) + assert mint_quote.request @pytest.mark.asyncio async def test_mint(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) if not settings.debug_mint_only_deprecated: - quote_resp = await wallet1.get_mint_quote(invoice.id) - assert quote_resp.request == invoice.bolt11 + quote_resp = await wallet1.get_mint_quote(mint_quote.quote) + assert quote_resp.request == mint_quote.request assert quote_resp.state == MintQuoteState.paid.value expected_proof_amounts = wallet1.split_wallet_state(64) - await wallet1.mint(64, id=invoice.id) + await wallet1.mint(64, quote_id=mint_quote.quote) assert wallet1.balance == 64 # verify that proofs in proofs_used db have the same mint_id as the invoice in the db - assert invoice.payment_hash - invoice_db = await get_lightning_invoice( - db=wallet1.db, payment_hash=invoice.payment_hash, out=False - ) - assert invoice_db + mint_quote = await get_bolt11_mint_quote(db=wallet1.db, quote=mint_quote.quote) + assert mint_quote proofs_minted = await get_proofs( - db=wallet1.db, mint_id=invoice_db.id, table="proofs" + db=wallet1.db, mint_id=mint_quote.quote, table="proofs" ) assert len(proofs_minted) == len(expected_proof_amounts) assert all([p.amount in expected_proof_amounts for p in proofs_minted]) - assert all([p.mint_id == invoice.id for p in proofs_minted]) + assert all([p.mint_id == mint_quote.quote for p in proofs_minted]) @pytest.mark.asyncio async def test_mint_amounts(wallet1: Wallet): """Mint predefined amounts""" amts = [1, 1, 1, 2, 2, 4, 16] - invoice = await wallet1.request_mint(sum(amts)) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(amount=sum(amts), split=amts, id=invoice.id) + mint_quote = await wallet1.request_mint(sum(amts)) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(amount=sum(amts), split=amts, quote_id=mint_quote.quote) assert wallet1.balance == 27 assert wallet1.proof_amounts == amts @@ -207,9 +209,9 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet): """Mint predefined amounts""" amts = [1, 1, 1, 2, 2, 4, 16] - invoice = await wallet1.request_mint(sum(amts)) + mint_quote = await wallet1.request_mint(sum(amts)) await assert_err( - wallet1.mint(amount=sum(amts) + 1, split=amts, id=invoice.id), + wallet1.mint(amount=sum(amts) + 1, split=amts, quote_id=mint_quote.quote), "split must sum to amount", ) @@ -218,18 +220,18 @@ async def test_mint_amounts_wrong_sum(wallet1: Wallet): async def test_mint_amounts_wrong_order(wallet1: Wallet): """Mint amount that is not part in 2^n""" amts = [1, 2, 3] - invoice = await wallet1.request_mint(sum(amts)) + mint_quote = await wallet1.request_mint(sum(amts)) await assert_err( - wallet1.mint(amount=sum(amts), split=[1, 2, 3], id=invoice.id), + wallet1.mint(amount=sum(amts), split=[1, 2, 3], quote_id=mint_quote.quote), f"Can only mint amounts with 2^n up to {2**settings.max_order}.", ) @pytest.mark.asyncio async def test_split(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) assert wallet1.balance == 64 # the outputs we keep that we expect after the split expected_proof_amounts = wallet1.split_wallet_state(44) @@ -247,9 +249,9 @@ async def test_split(wallet1: Wallet): @pytest.mark.asyncio async def test_swap_to_send(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) assert wallet1.balance == 64 # this will select 32 sats and them (nothing to keep) @@ -269,9 +271,9 @@ async def test_swap_to_send(wallet1: Wallet): @pytest.mark.asyncio async def test_split_more_than_balance(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await assert_err( wallet1.split(wallet1.proofs, 128), # "Mint Error: inputs do not have same amount as outputs", @@ -283,22 +285,19 @@ async def test_split_more_than_balance(wallet1: Wallet): @pytest.mark.asyncio async def test_melt(wallet1: Wallet): # mint twice so we have enough to pay the second invoice back - topup_invoice = await wallet1.request_mint(128) - await pay_if_regtest(topup_invoice.bolt11) - await wallet1.mint(128, id=topup_invoice.id) + topup_mint_quote = await wallet1.request_mint(128) + await pay_if_regtest(topup_mint_quote.request) + await wallet1.mint(128, quote_id=topup_mint_quote.quote) assert wallet1.balance == 128 invoice_payment_request = "" - invoice_payment_hash = "" if is_regtest: invoice_dict = get_real_invoice(64) - invoice_payment_hash = str(invoice_dict["r_hash"]) invoice_payment_request = invoice_dict["payment_request"] if is_fake: - invoice = await wallet1.request_mint(64) - invoice_payment_hash = str(invoice.payment_hash) - invoice_payment_request = invoice.bolt11 + mint_quote = await wallet1.request_mint(64) + invoice_payment_request = mint_quote.request quote = await wallet1.melt_quote(invoice_payment_request) total_amount = quote.amount + quote.fee_reserve @@ -334,17 +333,16 @@ async def test_melt(wallet1: Wallet): assert melt_response.change[0].id == send_proofs[0].id, "Wrong keyset returned" # verify that proofs in proofs_used db have the same melt_id as the invoice in the db - assert invoice_payment_hash, "No payment hash in invoice" - invoice_db = await get_lightning_invoice( - db=wallet1.db, payment_hash=invoice_payment_hash, out=True + melt_quote_db = await get_bolt11_melt_quote( + db=wallet1.db, request=invoice_payment_request ) - assert invoice_db, "No invoice in db" + assert melt_quote_db, "No invoice in db" proofs_used = await get_proofs( - db=wallet1.db, melt_id=invoice_db.id, table="proofs_used" + db=wallet1.db, melt_id=melt_quote_db.quote, table="proofs_used" ) assert len(proofs_used) == len(send_proofs), "Not all proofs used" - assert all([p.melt_id == invoice_db.id for p in proofs_used]), "Wrong melt_id" + assert all([p.melt_id == melt_quote_db.quote for p in proofs_used]), "Wrong melt_id" # the payment was without fees so we need to remove it from the total amount assert wallet1.balance == 128 - (total_amount - quote.fee_reserve), "Wrong balance" @@ -353,9 +351,9 @@ async def test_melt(wallet1: Wallet): @pytest.mark.asyncio async def test_swap_to_send_more_than_balance(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await assert_err( wallet1.swap_to_send(wallet1.proofs, 128, set_reserved=True), "balance too low.", @@ -366,9 +364,9 @@ async def test_swap_to_send_more_than_balance(wallet1: Wallet): @pytest.mark.asyncio async def test_double_spend(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - doublespend = await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + doublespend = await wallet1.mint(64, quote_id=mint_quote.quote) await wallet1.split(wallet1.proofs, 20) await assert_err( wallet1.split(doublespend, 20), @@ -380,9 +378,9 @@ async def test_double_spend(wallet1: Wallet): @pytest.mark.asyncio async def test_duplicate_proofs_double_spent(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - doublespend = await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + doublespend = await wallet1.mint(64, quote_id=mint_quote.quote) await assert_err( wallet1.split(wallet1.proofs + doublespend, 20), "Mint Error: duplicate proofs.", @@ -394,9 +392,9 @@ async def test_duplicate_proofs_double_spent(wallet1: Wallet): @pytest.mark.asyncio @pytest.mark.skipif(is_github_actions, reason="GITHUB_ACTIONS") async def test_split_race_condition(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) # run two splits in parallel import asyncio @@ -411,9 +409,9 @@ async def test_split_race_condition(wallet1: Wallet): @pytest.mark.asyncio async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) _, spendable_proofs = await wallet1.swap_to_send( wallet1.proofs, 32, set_reserved=True ) @@ -430,9 +428,9 @@ async def test_send_and_redeem(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_invalidate_all_proofs(wallet1: Wallet): """Try to invalidate proofs that have not been spent yet. Should not work!""" - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await wallet1.invalidate(wallet1.proofs) assert wallet1.balance == 0 @@ -440,18 +438,18 @@ async def test_invalidate_all_proofs(wallet1: Wallet): @pytest.mark.asyncio async def test_invalidate_unspent_proofs_with_checking(wallet1: Wallet): """Try to invalidate proofs that have not been spent yet but force no check.""" - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await wallet1.invalidate(wallet1.proofs, check_spendable=True) assert wallet1.balance == 64 @pytest.mark.asyncio async def test_split_invalid_amount(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await assert_err( wallet1.split(wallet1.proofs, -1), "amount can't be negative", @@ -460,9 +458,9 @@ async def test_split_invalid_amount(wallet1: Wallet): @pytest.mark.asyncio async def test_token_state(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) assert wallet1.balance == 64 resp = await wallet1.check_proof_state(wallet1.proofs) assert resp.states[0].state.value == "UNSPENT" diff --git a/tests/test_wallet_api.py b/tests/test_wallet_api.py index 2e391743..135eb2e7 100644 --- a/tests/test_wallet_api.py +++ b/tests/test_wallet_api.py @@ -33,12 +33,14 @@ async def test_invoice(wallet: Wallet): while state.pending: print("checking invoice state") response2 = client.get( - f"/lightning/invoice_state?payment_hash={invoice_response.checking_id}" + f"/lightning/invoice_state?payment_request={invoice_response.payment_request}" ) state = PaymentStatus.parse_obj(response2.json()) await asyncio.sleep(0.1) print("state:", state) print("paid") + await wallet.load_proofs() + assert wallet.available_balance >= 100 @pytest.mark.skipif(is_regtest, reason="regtest") @@ -175,7 +177,7 @@ async def test_flow(wallet: Wallet): while state.pending: print("checking invoice state") response2 = client.get( - f"/lightning/invoice_state?payment_hash={invoice_response.checking_id}" + f"/lightning/invoice_state?payment_request={invoice_response.payment_request}" ) state = PaymentStatus.parse_obj(response2.json()) await asyncio.sleep(0.1) diff --git a/tests/test_wallet_cli.py b/tests/test_wallet_cli.py index bb4331a1..fe6f06f2 100644 --- a/tests/test_wallet_cli.py +++ b/tests/test_wallet_cli.py @@ -32,6 +32,10 @@ def get_invoice_from_invoices_command(output: str) -> dict[str, str]: removed_empty_and_hiphens = [ value for value in splitted if value and not value.startswith("-----") ] + # filter only lines that have ": " in them + removed_empty_and_hiphens = [ + value for value in removed_empty_and_hiphens if ": " in value + ] dict_output = { f"{value.split(': ')[0]}": value.split(": ")[1] for value in removed_empty_and_hiphens @@ -41,7 +45,8 @@ def get_invoice_from_invoices_command(output: str) -> dict[str, str]: async def reset_invoices(wallet: Wallet): - await wallet.db.execute("DELETE FROM invoices") + await wallet.db.execute("DELETE FROM bolt11_melt_quotes") + await wallet.db.execute("DELETE FROM bolt11_mint_quotes") async def init_wallet(): @@ -204,8 +209,8 @@ def test_invoices_with_minting(cli_prefix): # arrange wallet1 = asyncio.run(init_wallet()) asyncio.run(reset_invoices(wallet=wallet1)) - invoice = asyncio.run(wallet1.request_mint(64)) - asyncio.run(pay_if_regtest(invoice.bolt11)) + mint_quote = asyncio.run(wallet1.request_mint(64)) + asyncio.run(pay_if_regtest(mint_quote.request)) # act runner = CliRunner() result = runner.invoke( @@ -217,18 +222,14 @@ def test_invoices_with_minting(cli_prefix): print("INVOICES --mint") assert result.exception is None assert result.exit_code == 0 - assert "No invoices found." not in result.output - assert "ID" in result.output - assert "Paid" in result.output - assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id - assert get_invoice_from_invoices_command(result.output)["Paid"] == "True" + assert "Received 64 sat" in result.output def test_invoices_without_minting(cli_prefix): # arrange wallet1 = asyncio.run(init_wallet()) asyncio.run(reset_invoices(wallet=wallet1)) - invoice = asyncio.run(wallet1.request_mint(64)) + mint_quote = asyncio.run(wallet1.request_mint(64)) # act runner = CliRunner() @@ -243,9 +244,11 @@ def test_invoices_without_minting(cli_prefix): assert result.exit_code == 0 assert "No invoices found." not in result.output assert "ID" in result.output - assert "Paid" in result.output - assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id - assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid) + assert "State" in result.output + assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote + assert get_invoice_from_invoices_command(result.output)["State"] == str( + mint_quote.state + ) @pytest.mark.skipif(not is_fake, reason="only on fakewallet") @@ -259,11 +262,11 @@ def test_invoices_with_onlypaid_option(cli_prefix): runner = CliRunner() result = runner.invoke( cli, - [*cli_prefix, "invoices", "--only-paid", "--mint"], + [*cli_prefix, "invoices", "--only-paid"], ) # assert - print("INVOICES --only-paid --mint") + print("INVOICES --only-paid") assert result.exception is None assert result.exit_code == 0 assert "No invoices found." in result.output @@ -314,7 +317,7 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix): # arrange wallet1 = asyncio.run(init_wallet()) asyncio.run(reset_invoices(wallet=wallet1)) - invoice = asyncio.run(wallet1.request_mint(64)) + mint_quote = asyncio.run(wallet1.request_mint(64)) # act runner = CliRunner() @@ -329,9 +332,11 @@ def test_invoices_with_onlyunpaid_option_without_minting(cli_prefix): assert result.exit_code == 0 assert "No invoices found." not in result.output assert "ID" in result.output - assert "Paid" in result.output - assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id - assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid) + assert "State" in result.output + assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote + assert get_invoice_from_invoices_command(result.output)["State"] == str( + mint_quote.state + ) def test_invoices_with_both_onlypaid_and_onlyunpaid_options(cli_prefix): @@ -374,7 +379,7 @@ def test_invoices_with_pending_option_without_minting(cli_prefix): # arrange wallet1 = asyncio.run(init_wallet()) asyncio.run(reset_invoices(wallet=wallet1)) - invoice = asyncio.run(wallet1.request_mint(64)) + mint_quote = asyncio.run(wallet1.request_mint(64)) # act runner = CliRunner() @@ -389,9 +394,11 @@ def test_invoices_with_pending_option_without_minting(cli_prefix): assert result.exit_code == 0 assert "No invoices found." not in result.output assert "ID" in result.output - assert "Paid" in result.output - assert get_invoice_from_invoices_command(result.output)["ID"] == invoice.id - assert get_invoice_from_invoices_command(result.output)["Paid"] == str(invoice.paid) + assert "State" in result.output + assert get_invoice_from_invoices_command(result.output)["ID"] == mint_quote.quote + assert get_invoice_from_invoices_command(result.output)["State"] == str( + mint_quote.state + ) def test_wallets(cli_prefix): diff --git a/tests/test_wallet_htlc.py b/tests/test_wallet_htlc.py index ce9b94b2..22da648c 100644 --- a/tests/test_wallet_htlc.py +++ b/tests/test_wallet_htlc.py @@ -57,9 +57,9 @@ async def wallet2(): @pytest.mark.asyncio async def test_create_htlc_secret(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() secret = await wallet1.create_htlc_lock(preimage=preimage) @@ -68,9 +68,9 @@ async def test_create_htlc_secret(wallet1: Wallet): @pytest.mark.asyncio async def test_htlc_split(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() secret = await wallet1.create_htlc_lock(preimage=preimage) @@ -81,9 +81,9 @@ async def test_htlc_split(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() secret = await wallet1.create_htlc_lock(preimage=preimage) @@ -95,9 +95,9 @@ async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() secret = await wallet1.create_htlc_lock( @@ -113,9 +113,9 @@ async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet) @pytest.mark.asyncio async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() @@ -133,9 +133,9 @@ async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() @@ -157,9 +157,9 @@ async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet @pytest.mark.asyncio async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest() @@ -177,9 +177,9 @@ async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wall @pytest.mark.asyncio async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() @@ -201,9 +201,9 @@ async def test_htlc_redeem_with_2_of_1_signatures(wallet1: Wallet, wallet2: Wall @pytest.mark.asyncio async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() @@ -227,9 +227,9 @@ async def test_htlc_redeem_with_2_of_2_signatures(wallet1: Wallet, wallet2: Wall async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = pubkey_wallet1 @@ -256,9 +256,9 @@ async def test_htlc_redeem_with_2_of_2_signatures_with_duplicate_pubkeys( async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() @@ -285,9 +285,9 @@ async def test_htlc_redeem_with_3_of_3_signatures_but_only_2_provided( async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_provided( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() @@ -316,9 +316,9 @@ async def test_htlc_redeem_with_2_of_3_signatures_with_2_valid_and_1_invalid_pro async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_provided( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() @@ -349,9 +349,9 @@ async def test_htlc_redeem_with_3_of_3_signatures_with_2_valid_and_1_invalid_pro async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() @@ -383,9 +383,9 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature( async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) preimage = "00000000000000000000000000000000" pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() diff --git a/tests/test_wallet_lightning.py b/tests/test_wallet_lightning.py index b9b3cc6e..b8b11476 100644 --- a/tests/test_wallet_lightning.py +++ b/tests/test_wallet_lightning.py @@ -81,8 +81,7 @@ async def test_check_invoice_internal(wallet: LightningWallet): # fill wallet invoice = await wallet.create_invoice(64) assert invoice.payment_request - assert invoice.checking_id - status = await wallet.get_invoice_status(invoice.checking_id) + status = await wallet.get_invoice_status(invoice.payment_request) assert status.settled @@ -92,11 +91,10 @@ async def test_check_invoice_external(wallet: LightningWallet): # fill wallet invoice = await wallet.create_invoice(64) assert invoice.payment_request - assert invoice.checking_id - status = await wallet.get_invoice_status(invoice.checking_id) + status = await wallet.get_invoice_status(invoice.payment_request) assert not status.settled await pay_if_regtest(invoice.payment_request) - status = await wallet.get_invoice_status(invoice.checking_id) + status = await wallet.get_invoice_status(invoice.payment_request) assert status.settled @@ -106,8 +104,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet): # fill wallet invoice = await wallet.create_invoice(64) assert invoice.payment_request - assert invoice.checking_id - await wallet.get_invoice_status(invoice.checking_id) + await wallet.get_invoice_status(invoice.payment_request) assert wallet.available_balance >= 64 # pay invoice @@ -118,8 +115,7 @@ async def test_pay_invoice_internal(wallet: LightningWallet): assert status.settled # check payment - assert invoice2.checking_id - status = await wallet.get_payment_status(invoice2.checking_id) + status = await wallet.get_payment_status(invoice2.payment_request) assert status.settled @@ -129,9 +125,8 @@ async def test_pay_invoice_external(wallet: LightningWallet): # fill wallet invoice = await wallet.create_invoice(64) assert invoice.payment_request - assert invoice.checking_id await pay_if_regtest(invoice.payment_request) - status = await wallet.get_invoice_status(invoice.checking_id) + status = await wallet.get_invoice_status(invoice.payment_request) assert status.settled assert wallet.available_balance >= 64 @@ -141,7 +136,5 @@ async def test_pay_invoice_external(wallet: LightningWallet): assert status.settled - # check payment - assert status.checking_id - status = await wallet.get_payment_status(status.checking_id) + # check payment) assert status.settled diff --git a/tests/test_wallet_p2pk.py b/tests/test_wallet_p2pk.py index 3414f2a9..94afbc50 100644 --- a/tests/test_wallet_p2pk.py +++ b/tests/test_wallet_p2pk.py @@ -59,18 +59,18 @@ async def wallet2(): @pytest.mark.asyncio async def test_create_p2pk_pubkey(wallet1: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey = await wallet1.create_p2pk_pubkey() PublicKey(bytes.fromhex(pubkey), raw=True) @pytest.mark.asyncio async def test_p2pk(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # p2pk test secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side @@ -92,9 +92,9 @@ async def test_p2pk(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # p2pk test secret_lock = await wallet1.create_p2pk_lock( @@ -108,9 +108,9 @@ async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side # sender side secret_lock = await wallet1.create_p2pk_lock(pubkey_wallet2) # sender side @@ -129,9 +129,9 @@ async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wal async def test_p2pk_short_locktime_receive_with_wrong_private_key( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side # sender side secret_lock = await wallet1.create_p2pk_lock( @@ -155,9 +155,9 @@ async def test_p2pk_short_locktime_receive_with_wrong_private_key( @pytest.mark.asyncio async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side # sender side garbage_pubkey = PrivateKey().pubkey @@ -184,9 +184,9 @@ async def test_p2pk_locktime_with_refund_pubkey(wallet1: Wallet, wallet2: Wallet @pytest.mark.asyncio async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await wallet2.create_p2pk_pubkey() # receiver side # sender side garbage_pubkey = PrivateKey().pubkey @@ -220,9 +220,9 @@ async def test_p2pk_locktime_with_wrong_refund_pubkey(wallet1: Wallet, wallet2: async def test_p2pk_locktime_with_second_refund_pubkey( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet1 = await wallet1.create_p2pk_pubkey() # receiver side pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # receiver side # sender side @@ -252,9 +252,9 @@ async def test_p2pk_locktime_with_second_refund_pubkey( @pytest.mark.asyncio async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() assert pubkey_wallet1 != pubkey_wallet2 @@ -274,9 +274,9 @@ async def test_p2pk_multisig_2_of_2(wallet1: Wallet, wallet2: Wallet): @pytest.mark.asyncio async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() assert pubkey_wallet1 != pubkey_wallet2 @@ -298,9 +298,9 @@ async def test_p2pk_multisig_duplicate_signature(wallet1: Wallet, wallet2: Walle @pytest.mark.asyncio async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() assert pubkey_wallet1 != pubkey_wallet2 @@ -319,9 +319,9 @@ async def test_p2pk_multisig_quorum_not_met_1_of_2(wallet1: Wallet, wallet2: Wal @pytest.mark.asyncio async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet1 = await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() assert pubkey_wallet1 != pubkey_wallet2 @@ -344,9 +344,9 @@ async def test_p2pk_multisig_quorum_not_met_2_of_3(wallet1: Wallet, wallet2: Wal @pytest.mark.asyncio async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2: Wallet): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) pubkey_wallet2 = await wallet2.create_p2pk_pubkey() # p2pk test secret_lock = await wallet1.create_p2pk_lock( @@ -362,9 +362,9 @@ async def test_p2pk_multisig_with_duplicate_publickey(wallet1: Wallet, wallet2: async def test_p2pk_multisig_with_wrong_first_private_key( wallet1: Wallet, wallet2: Wallet ): - invoice = await wallet1.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet1.mint(64, id=invoice.id) + mint_quote = await wallet1.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet1.mint(64, quote_id=mint_quote.quote) await wallet1.create_p2pk_pubkey() pubkey_wallet2 = await wallet2.create_p2pk_pubkey() wrong_pubklic_key = PrivateKey().pubkey diff --git a/tests/test_wallet_regtest.py b/tests/test_wallet_regtest.py index a9a792d2..e4cfc6ef 100644 --- a/tests/test_wallet_regtest.py +++ b/tests/test_wallet_regtest.py @@ -32,9 +32,9 @@ async def wallet(): @pytest.mark.skipif(is_fake, reason="only regtest") async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice @@ -70,9 +70,9 @@ async def test_regtest_pending_quote(wallet: Wallet, ledger: Ledger): @pytest.mark.skipif(is_fake, reason="only regtest") async def test_regtest_failed_quote(wallet: Wallet, ledger: Ledger): # fill wallet - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) assert wallet.balance == 64 # create hodl invoice diff --git a/tests/test_wallet_regtest_mpp.py b/tests/test_wallet_regtest_mpp.py index 8e94f6e3..8233cd6a 100644 --- a/tests/test_wallet_regtest_mpp.py +++ b/tests/test_wallet_regtest_mpp.py @@ -40,9 +40,9 @@ async def test_regtest_pay_mpp(wallet: Wallet, ledger: Ledger): assert wallet.mint_info.supports_mpp("bolt11", wallet.unit) # top up wallet twice so we have enough for two payments - topup_invoice = await wallet.request_mint(128) - await pay_if_regtest(topup_invoice.bolt11) - proofs1 = await wallet.mint(128, id=topup_invoice.id) + topup_mint_quote = await wallet.request_mint(128) + await pay_if_regtest(topup_mint_quote.request) + proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote) assert wallet.balance == 128 # this is the invoice we want to pay in two parts @@ -95,19 +95,19 @@ async def test_regtest_pay_mpp_incomplete_payment(wallet: Wallet, ledger: Ledger assert wallet.mint_info.supports_mpp("bolt11", wallet.unit) # top up wallet twice so we have enough for three payments - topup_invoice = await wallet.request_mint(128) - await pay_if_regtest(topup_invoice.bolt11) - proofs1 = await wallet.mint(128, id=topup_invoice.id) + topup_mint_quote = await wallet.request_mint(128) + await pay_if_regtest(topup_mint_quote.request) + proofs1 = await wallet.mint(128, quote_id=topup_mint_quote.quote) assert wallet.balance == 128 - topup_invoice = await wallet.request_mint(128) - await pay_if_regtest(topup_invoice.bolt11) - proofs2 = await wallet.mint(128, id=topup_invoice.id) + topup_mint_quote = await wallet.request_mint(128) + await pay_if_regtest(topup_mint_quote.request) + proofs2 = await wallet.mint(128, quote_id=topup_mint_quote.quote) assert wallet.balance == 256 - topup_invoice = await wallet.request_mint(128) - await pay_if_regtest(topup_invoice.bolt11) - proofs3 = await wallet.mint(128, id=topup_invoice.id) + topup_mint_quote = await wallet.request_mint(128) + await pay_if_regtest(topup_mint_quote.request) + proofs3 = await wallet.mint(128, quote_id=topup_mint_quote.quote) assert wallet.balance == 384 # this is the invoice we want to pay in two parts diff --git a/tests/test_wallet_restore.py b/tests/test_wallet_restore.py index 0755db11..5866a527 100644 --- a/tests/test_wallet_restore.py +++ b/tests/test_wallet_restore.py @@ -156,9 +156,9 @@ async def test_generate_secrets_from_to(wallet3: Wallet): @pytest.mark.asyncio async def test_restore_wallet_after_mint(wallet3: Wallet): await reset_wallet_db(wallet3) - invoice = await wallet3.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet3.mint(64, id=invoice.id) + mint_quote = await wallet3.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet3.mint(64, quote_id=mint_quote.quote) assert wallet3.balance == 64 await reset_wallet_db(wallet3) await wallet3.load_proofs() @@ -192,9 +192,9 @@ async def test_restore_wallet_after_swap_to_send(wallet3: Wallet): ) await reset_wallet_db(wallet3) - invoice = await wallet3.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet3.mint(64, id=invoice.id) + mint_quote = await wallet3.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet3.mint(64, quote_id=mint_quote.quote) assert wallet3.balance == 64 _, spendable_proofs = await wallet3.swap_to_send( @@ -217,9 +217,9 @@ async def test_restore_wallet_after_send_and_receive(wallet3: Wallet, wallet2: W "hello rug want adapt talent together lunar method bean expose beef position" ) await reset_wallet_db(wallet3) - invoice = await wallet3.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet3.mint(64, id=invoice.id) + mint_quote = await wallet3.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet3.mint(64, quote_id=mint_quote.quote) assert wallet3.balance == 64 _, spendable_proofs = await wallet3.swap_to_send( @@ -260,9 +260,9 @@ async def test_restore_wallet_after_send_and_self_receive(wallet3: Wallet): ) await reset_wallet_db(wallet3) - invoice = await wallet3.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet3.mint(64, id=invoice.id) + mint_quote = await wallet3.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet3.mint(64, quote_id=mint_quote.quote) assert wallet3.balance == 64 _, spendable_proofs = await wallet3.swap_to_send( @@ -289,9 +289,9 @@ async def test_restore_wallet_after_send_twice( wallet3.private_key = PrivateKey() await reset_wallet_db(wallet3) - invoice = await wallet3.request_mint(2) - await pay_if_regtest(invoice.bolt11) - await wallet3.mint(2, id=invoice.id) + mint_quote = await wallet3.request_mint(2) + await pay_if_regtest(mint_quote.request) + await wallet3.mint(2, quote_id=mint_quote.quote) box.add(wallet3.proofs) assert wallet3.balance == 2 @@ -348,9 +348,9 @@ async def test_restore_wallet_after_send_and_self_receive_nonquadratic_value( ) await reset_wallet_db(wallet3) - invoice = await wallet3.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet3.mint(64, id=invoice.id) + mint_quote = await wallet3.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet3.mint(64, quote_id=mint_quote.quote) box.add(wallet3.proofs) assert wallet3.balance == 64 diff --git a/tests/test_wallet_subscription.py b/tests/test_wallet_subscription.py index dd07cbb6..94c26526 100644 --- a/tests/test_wallet_subscription.py +++ b/tests/test_wallet_subscription.py @@ -44,10 +44,10 @@ def callback(msg: JSONRPCNotficationParams): nonlocal triggered, msg_stack triggered = True msg_stack.append(msg) - asyncio.run(wallet.mint(int(invoice.amount), id=invoice.id)) + asyncio.run(wallet.mint(int(mint_quote.amount), quote_id=mint_quote.quote)) - invoice, sub = await wallet.request_mint_with_callback(128, callback=callback) - await pay_if_regtest(invoice.bolt11) + mint_quote, sub = await wallet.request_mint_with_callback(128, callback=callback) + await pay_if_regtest(mint_quote.request) wait = settings.fakewallet_delay_incoming_payment or 2 await asyncio.sleep(wait + 2) @@ -66,9 +66,9 @@ async def test_wallet_subscription_swap(wallet: Wallet): if not wallet.mint_info.supports_nut(WEBSOCKETS_NUT): pytest.skip("No websocket support") - invoice = await wallet.request_mint(64) - await pay_if_regtest(invoice.bolt11) - await wallet.mint(64, id=invoice.id) + mint_quote = await wallet.request_mint(64) + await pay_if_regtest(mint_quote.request) + await wallet.mint(64, quote_id=mint_quote.quote) triggered = False msg_stack: list[JSONRPCNotficationParams] = []