request fee from mint

This commit is contained in:
callebtc
2022-10-05 22:26:57 +02:00
parent 16eb3cf6c5
commit 2d48c3116c
7 changed files with 44 additions and 17 deletions

View File

@@ -153,10 +153,14 @@ class CheckRequest(BaseModel):
proofs: List[Proof]
class CheckInternalRequest(BaseModel):
class CheckFeesRequest(BaseModel):
pr: str
class CheckFeesResponse(BaseModel):
fee: Union[int, None]
class MeltRequest(BaseModel):
proofs: List[Proof]
amount: int = None # deprecated

View File

@@ -28,8 +28,10 @@ def async_unwrap(to_await):
return async_response[0]
def fee_reserve(amount_msat: int) -> int:
def fee_reserve(amount_msat: int, internal=False) -> int:
"""Function for calculating the Lightning fee reserve"""
if internal:
return 0
return max(
int(LIGHTNING_RESERVE_FEE_MIN), int(amount_msat * LIGHTNING_FEE_PERCENT / 100.0)
)

View File

@@ -116,6 +116,8 @@ class LNbitsWallet(Wallet):
)
except:
return PaymentStatus(None)
if r.json().get("detail"):
return PaymentStatus(None)
return PaymentStatus(r.json()["paid"])
async def get_payment_status(self, checking_id: str) -> PaymentStatus:

View File

@@ -197,13 +197,13 @@ class Ledger:
await update_lightning_invoice(payment_hash, issued=True, db=self.db)
return status.paid
async def _pay_lightning_invoice(self, invoice: str, amount: int):
async def _pay_lightning_invoice(self, invoice: str, fees_msat: int):
"""Returns an invoice from the Lightning backend."""
error, _ = await WALLET.status()
if error:
raise Exception(f"Lightning wallet not responding: {error}")
ok, checking_id, fee_msat, preimage, error_message = await WALLET.pay_invoice(
invoice, fee_limit_msat=fee_reserve(amount * 1000)
invoice, fee_limit_msat=fees_msat
)
return ok, preimage
@@ -258,16 +258,15 @@ class Ledger:
if not all([self._verify_proof(p) for p in proofs]):
raise Exception("could not verify proofs.")
total = sum([p["amount"] for p in proofs])
total_provided = sum([p["amount"] for p in proofs])
invoice_obj = bolt11.decode(invoice)
amount = math.ceil(invoice_obj.amount_msat / 1000)
# check that lightning fees are included
assert total + fee_reserve(amount * 1000) >= amount, Exception(
fees_msat = await self.check_fees(invoice)
assert total_provided >= amount + fees_msat / 1000, Exception(
"provided proofs not enough for Lightning payment."
)
status, preimage = await self._pay_lightning_invoice(invoice, amount)
status, preimage = await self._pay_lightning_invoice(invoice, fees_msat)
if status == True:
await self._invalidate_proofs(proofs)
return status, preimage
@@ -276,6 +275,17 @@ class Ledger:
"""Checks if all provided proofs are valid and still spendable (i.e. have not been spent)."""
return {i: self._check_spendable(p) for i, p in enumerate(proofs)}
async def check_fees(self, pr: str):
"""Returns the fees (in msat) required to pay this pr."""
decoded_invoice = bolt11.decode(pr)
amount = math.ceil(decoded_invoice.amount_msat / 1000)
# hack: check if it's internal, if it exists, it will return paid = False,
# if id does not exist (not internal), it returns paid = None
paid = await WALLET.get_invoice_status(decoded_invoice.payment_hash)
internal = paid.paid == False
fees_msat = fee_reserve(amount * 1000, internal)
return fees_msat
async def split(
self, proofs: List[Proof], amount: int, outputs: List[BlindedMessage]
):

View File

@@ -5,7 +5,9 @@ from secp256k1 import PublicKey
from cashu.core.base import (
CashuError,
CheckFeesResponse,
CheckRequest,
CheckFeesRequest,
GetMeltResponse,
GetMintResponse,
MeltRequest,
@@ -72,6 +74,12 @@ async def check_spendable(payload: CheckRequest):
return await ledger.check_spendable(payload.proofs)
@router.post("/checkfees")
async def check_fees(payload: CheckFeesRequest):
fees_msat = await ledger.check_fees(payload.pr)
return CheckFeesResponse(fee=fees_msat / 1000)
@router.post("/split")
async def split(payload: SplitRequest):
"""

View File

@@ -17,7 +17,7 @@ from loguru import logger
import cashu.core.bolt11 as bolt11
from cashu.core.base import Proof
from cashu.core.bolt11 import Invoice
from cashu.core.bolt11 import Invoice, decode
from cashu.core.helpers import fee_reserve
from cashu.core.migrations import migrate_databases
from cashu.core.settings import CASHU_DIR, DEBUG, ENV_FILE, LIGHTNING, MINT_URL, VERSION
@@ -125,8 +125,10 @@ async def pay(ctx, invoice: str):
wallet.load_mint()
wallet.status()
decoded_invoice: Invoice = bolt11.decode(invoice)
# check if it's an internal payment
fees = (await wallet.check_fees(invoice))["fee"]
amount = math.ceil(
(decoded_invoice.amount_msat + fee_reserve(decoded_invoice.amount_msat)) / 1000
(decoded_invoice.amount_msat + fees * 1000) / 1000
) # 1% fee for Lightning
print(
f"Paying Lightning invoice of {decoded_invoice.amount_msat//1000} sat ({amount} sat incl. fees)"

View File

@@ -11,7 +11,7 @@ import cashu.core.b_dhke as b_dhke
from cashu.core.base import (
BlindedMessage,
BlindedSignature,
CheckInternalRequest,
CheckFeesRequest,
CheckRequest,
MeltRequest,
MintRequest,
@@ -211,14 +211,13 @@ class LedgerAPI:
return return_dict
async def check_internal(self, payment_request: str):
async def check_fees(self, payment_request: str):
"""Checks whether the Lightning payment is internal."""
payload = CheckInternalRequest(pr=payment_request)
payload = CheckFeesRequest(pr=payment_request)
return_dict = requests.post(
self.url + "/checkinternal",
self.url + "/checkfees",
json=payload.dict(),
).json()
return return_dict
async def pay_lightning(self, proofs: List[Proof], invoice: str):