Skip to content

Commit

Permalink
use melt_quote as argument for pay_invoice
Browse files Browse the repository at this point in the history
  • Loading branch information
callebtc committed Nov 21, 2023
1 parent 4704b40 commit 9dc2a62
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 29 deletions.
4 changes: 2 additions & 2 deletions cashu/lightning/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from pydantic import BaseModel

from ..core.base import Amount, Unit
from ..core.base import Amount, MeltQuote, Unit


class StatusResponse(BaseModel):
Expand Down Expand Up @@ -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

Expand Down
10 changes: 6 additions & 4 deletions cashu/lightning/corelightningrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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,
Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions cashu/lightning/fake.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions cashu/lightning/lnbits.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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()
Expand Down
8 changes: 5 additions & 3 deletions cashu/lightning/lndrest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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,
)

Expand Down
27 changes: 19 additions & 8 deletions cashu/lightning/strike.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 4 additions & 0 deletions cashu/mint/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand All @@ -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)}"
Expand Down
2 changes: 1 addition & 1 deletion cashu/mint/ledger.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
9 changes: 6 additions & 3 deletions cashu/mint/startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
6 changes: 4 additions & 2 deletions cashu/wallet/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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:
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 9dc2a62

Please sign in to comment.