From 9dc2a627e147633f2060a7ac84a6e21fef4dd3f2 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Tue, 21 Nov 2023 18:25:13 -0300 Subject: [PATCH] use melt_quote as argument for pay_invoice --- cashu/lightning/base.py | 4 ++-- cashu/lightning/corelightningrest.py | 10 ++++++---- cashu/lightning/fake.py | 6 +++--- cashu/lightning/lnbits.py | 8 +++++--- cashu/lightning/lndrest.py | 8 +++++--- cashu/lightning/strike.py | 27 +++++++++++++++++++-------- cashu/mint/crud.py | 4 ++++ cashu/mint/ledger.py | 2 +- cashu/mint/startup.py | 9 ++++++--- cashu/wallet/cli/cli.py | 6 ++++-- 10 files changed, 55 insertions(+), 29 deletions(-) diff --git a/cashu/lightning/base.py b/cashu/lightning/base.py index 6763ed2c..089a0290 100644 --- a/cashu/lightning/base.py +++ b/cashu/lightning/base.py @@ -3,7 +3,7 @@ from pydantic import BaseModel -from ..core.base import Amount, Unit +from ..core.base import Amount, MeltQuote, Unit class StatusResponse(BaseModel): @@ -83,7 +83,7 @@ def create_invoice( @abstractmethod def pay_invoice( - self, bolt11: str, fee_limit_msat: int + self, quote: MeltQuote, fee_limit_msat: int ) -> Coroutine[None, None, PaymentResponse]: pass diff --git a/cashu/lightning/corelightningrest.py b/cashu/lightning/corelightningrest.py index d95478f8..0728989e 100644 --- a/cashu/lightning/corelightningrest.py +++ b/cashu/lightning/corelightningrest.py @@ -10,7 +10,7 @@ ) from loguru import logger -from ..core.base import Amount, Unit +from ..core.base import Amount, MeltQuote, Unit from ..core.helpers import fee_reserve from ..core.settings import settings from .base import ( @@ -147,9 +147,11 @@ async def create_invoice( error_message=None, ) - async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse: + async def pay_invoice( + self, quote: MeltQuote, fee_limit_msat: int + ) -> PaymentResponse: try: - invoice = decode(bolt11) + invoice = decode(quote.request) except Bolt11Exception as exc: return PaymentResponse( ok=False, @@ -172,7 +174,7 @@ async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse r = await self.client.post( f"{self.url}/v1/pay", data={ - "invoice": bolt11, + "invoice": quote.request, "maxfeepercent": f"{fee_limit_percent:.11}", "exemptfee": 0, # so fee_limit_percent is applied even on payments # with fee < 5000 millisatoshi (which is default value of exemptfee) diff --git a/cashu/lightning/fake.py b/cashu/lightning/fake.py index 94a8062b..d219123c 100644 --- a/cashu/lightning/fake.py +++ b/cashu/lightning/fake.py @@ -14,7 +14,7 @@ encode, ) -from ..core.base import Amount, Unit +from ..core.base import Amount, MeltQuote, Unit from ..core.helpers import fee_reserve from ..core.settings import settings from .base import ( @@ -94,8 +94,8 @@ async def create_invoice( ok=True, checking_id=payment_hash, payment_request=payment_request ) - async def pay_invoice(self, bolt11: str, fee_limit: int) -> PaymentResponse: - invoice = decode(bolt11) + async def pay_invoice(self, quote: MeltQuote, fee_limit: int) -> PaymentResponse: + invoice = decode(quote.request) if settings.fakewallet_delay_payment: await asyncio.sleep(5) diff --git a/cashu/lightning/lnbits.py b/cashu/lightning/lnbits.py index 143ed4f2..0ee3b458 100644 --- a/cashu/lightning/lnbits.py +++ b/cashu/lightning/lnbits.py @@ -6,7 +6,7 @@ decode, ) -from ..core.base import Amount, Unit +from ..core.base import Amount, MeltQuote, Unit from ..core.helpers import fee_reserve from ..core.settings import settings from .base import ( @@ -93,11 +93,13 @@ async def create_invoice( payment_request=payment_request, ) - async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse: + async def pay_invoice( + self, quote: MeltQuote, fee_limit_msat: int + ) -> PaymentResponse: try: r = await self.client.post( url=f"{self.endpoint}/api/v1/payments", - json={"out": True, "bolt11": bolt11}, + json={"out": True, "bolt11": quote.request}, timeout=None, ) r.raise_for_status() diff --git a/cashu/lightning/lndrest.py b/cashu/lightning/lndrest.py index ee660025..15251680 100644 --- a/cashu/lightning/lndrest.py +++ b/cashu/lightning/lndrest.py @@ -10,7 +10,7 @@ ) from loguru import logger -from ..core.base import Amount, Unit +from ..core.base import Amount, MeltQuote, Unit from ..core.helpers import fee_reserve from ..core.settings import settings from .base import ( @@ -139,14 +139,16 @@ async def create_invoice( error_message=None, ) - async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse: + async def pay_invoice( + self, quote: MeltQuote, fee_limit_msat: int + ) -> PaymentResponse: # set the fee limit for the payment lnrpcFeeLimit = dict() lnrpcFeeLimit["fixed_msat"] = f"{fee_limit_msat}" r = await self.client.post( url="/v1/channels/transactions", - json={"payment_request": bolt11, "fee_limit": lnrpcFeeLimit}, + json={"payment_request": quote.request, "fee_limit": lnrpcFeeLimit}, timeout=None, ) diff --git a/cashu/lightning/strike.py b/cashu/lightning/strike.py index 4499f437..c755ad17 100644 --- a/cashu/lightning/strike.py +++ b/cashu/lightning/strike.py @@ -4,7 +4,7 @@ import httpx -from ..core.base import Amount, Unit +from ..core.base import Amount, MeltQuote, Unit from ..core.settings import settings from .base import ( InvoiceResponse, @@ -76,7 +76,7 @@ async def create_invoice( payload = { "correlationId": secrets.token_hex(16), "description": "Invoice for order 123", - "amount": {"amount": str(amount / 100), "currency": "USD"}, + "amount": {"amount": str(amount.amount / 100), "currency": "USD"}, } try: r = await self.client.post(url=f"{self.endpoint}/v1/invoices", json=payload) @@ -131,30 +131,41 @@ async def get_payment_quote(self, bolt11: str) -> PaymentQuoteResponse: amount_cent = int(float(data.get("amount").get("amount")) * 100) quote = PaymentQuoteResponse( - amount=amount_cent, id=data.get("paymentQuoteId"), fee=Amount(Unit.msat, 0) + amount=Amount(Unit.usd, amount=amount_cent), + checking_id=data.get("paymentQuoteId"), + fee=Amount(Unit.usd, 0), ) return quote - async def pay_invoice(self, bolt11: str, fee_limit_msat: int) -> PaymentResponse: + async def pay_invoice( + self, quote: MeltQuote, fee_limit_msat: int + ) -> PaymentResponse: + # we need to get the checking_id of this quote try: r = await self.client.patch( - url=f"{self.endpoint}/v1/payment-quotes/{bolt11}/execute", + url=f"{self.endpoint}/v1/payment-quotes/{quote.checking_id}/execute", timeout=None, ) r.raise_for_status() except Exception: error_message = r.json()["data"]["message"] - return PaymentResponse(None, None, None, None, error_message) + return PaymentResponse( + ok=None, + checking_id=None, + fee=None, + preimage=None, + error_message=error_message, + ) data = r.json() states = {"PENDING": None, "COMPLETED": True, "FAILED": False} if states[data.get("state")]: return PaymentResponse( - ok=True, checking_id=None, fee=None, error_message=None + ok=True, checking_id=None, fee=None, preimage=None, error_message=None ) else: return PaymentResponse( - ok=False, checking_id=None, fee=None, error_message=None + ok=False, checking_id=None, fee=None, preimage=None, error_message=None ) async def get_invoice_status(self, checking_id: str) -> PaymentStatus: diff --git a/cashu/mint/crud.py b/cashu/mint/crud.py index 2f2287ba..91a360c5 100644 --- a/cashu/mint/crud.py +++ b/cashu/mint/crud.py @@ -460,6 +460,7 @@ async def get_melt_quote( quote_id: str, db: Database, checking_id: Optional[str] = None, + request: Optional[str] = None, conn: Optional[Connection] = None, ) -> Optional[MeltQuote]: clauses = [] @@ -470,6 +471,9 @@ async def get_melt_quote( if checking_id: clauses.append("checking_id = ?") values.append(checking_id) + if request: + clauses.append("request = ?") + values.append(request) where = "" if clauses: where = f"WHERE {' AND '.join(clauses)}" diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index 37b907dd..37104838 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -495,7 +495,7 @@ async def melt( # TODO: Check if melt_quote.fee_reserve is always the correct unit! logger.debug(f"Lightning: pay invoice {bolt11_request}") payment = await self.backends[method][unit].pay_invoice( - bolt11_request, melt_quote.fee_reserve * 1000 + melt_quote, melt_quote.fee_reserve * 1000 ) logger.trace("paid lightning invoice") diff --git a/cashu/mint/startup.py b/cashu/mint/startup.py index 8bac0e38..6e5d6c99 100644 --- a/cashu/mint/startup.py +++ b/cashu/mint/startup.py @@ -21,14 +21,17 @@ wallets_module = importlib.import_module("cashu.lightning") lightning_backend = getattr(wallets_module, settings.mint_lightning_backend)() +assert settings.mint_private_key is not None, "No mint private key set." + # strike_backend = getattr(wallets_module, "StrikeUSDWallet")() -# assert settings.mint_private_key is not None, "No mint private key set." # backends = { # Method.bolt11: {Unit.sat: lightning_backend, Unit.usd: strike_backend}, # } - +# backends = { +# Method.bolt11: {Unit.sat: lightning_backend, Unit.msat: lightning_backend}, +# } backends = { - Method.bolt11: {Unit.sat: lightning_backend, Unit.msat: lightning_backend}, + Method.bolt11: {Unit.sat: lightning_backend}, } ledger = Ledger( db=Database("mint", settings.mint_database), diff --git a/cashu/wallet/cli/cli.py b/cashu/wallet/cli/cli.py index f1dd2f57..50bbe59d 100644 --- a/cashu/wallet/cli/cli.py +++ b/cashu/wallet/cli/cli.py @@ -208,7 +208,7 @@ async def pay(ctx: Context, invoice: str, yes: bool): @cli.command("invoice", help="Create Lighting invoice.") -@click.argument("amount", type=int) +@click.argument("amount", type=float) @click.option("--id", default="", help="Id of the paid invoice.", type=str) @click.option( "--split", @@ -231,6 +231,7 @@ async def invoice(ctx: Context, amount: int, id: str, split: int, no_check: bool wallet: Wallet = ctx.obj["WALLET"] await wallet.load_mint() print_balance(ctx) + amount = int(amount * 100) if wallet.unit == Unit.usd else int(amount) # in case the user wants a specific split, we create a list of amounts optional_split = None if split: @@ -376,7 +377,7 @@ async def balance(ctx: Context, verbose): @cli.command("send", help="Send tokens.") -@click.argument("amount", type=int) +@click.argument("amount", type=float) @click.argument("nostr", type=str, required=False) @click.option( "--nostr", @@ -436,6 +437,7 @@ async def send_command( nosplit: bool, ): wallet: Wallet = ctx.obj["WALLET"] + amount = int(amount * 100) if wallet.unit == Unit.usd else int(amount) if not nostr and not nopt: await send( wallet,