From 64028d559f8a302e2d1a0535ccfca4cbdb6e0930 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 7 Oct 2022 21:53:04 +0300 Subject: [PATCH 1/6] feat: add `MINT_URL` env var for 3rd party mints --- .env.example | 1 + cashu/core/settings.py | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 78504b0..2348d62 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,7 @@ CASHU_DIR=~/.cashu # WALLET +# MINT_URL=http://localhost:8000/cashu/api/v1/cashu/SUVB2UrJSd9LKmn6aoSpVq MINT_HOST=127.0.0.1 MINT_PORT=3338 diff --git a/cashu/core/settings.py b/cashu/core/settings.py index 5a95fbf..b7b2ccd 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -34,13 +34,15 @@ MINT_PRIVATE_KEY = env.str("MINT_PRIVATE_KEY", default=None) MINT_SERVER_HOST = env.str("MINT_SERVER_HOST", default="127.0.0.1") MINT_SERVER_PORT = env.int("MINT_SERVER_PORT", default=3338) +MINT_URL = env.str("MINT_URL") MINT_HOST = env.str("MINT_HOST", default="8333.space") MINT_PORT = env.int("MINT_PORT", default=3338) -if MINT_HOST in ["localhost", "127.0.0.1"]: - MINT_URL = f"http://{MINT_HOST}:{MINT_PORT}" -else: - MINT_URL = f"https://{MINT_HOST}:{MINT_PORT}" +if not MINT_URL: + if MINT_HOST in ["localhost", "127.0.0.1"]: + MINT_URL = f"http://{MINT_HOST}:{MINT_PORT}" + else: + MINT_URL = f"https://{MINT_HOST}:{MINT_PORT}" LNBITS_ENDPOINT = env.str("LNBITS_ENDPOINT", default=None) LNBITS_KEY = env.str("LNBITS_KEY", default=None) From 80bd3c6d3a0f34b67394357ed4158b7204223975 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 7 Oct 2022 22:26:38 +0300 Subject: [PATCH 2/6] fix: check requested amount against the paid invoice amount --- cashu/mint/ledger.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cashu/mint/ledger.py b/cashu/mint/ledger.py index 501eaa4..26f6ee1 100644 --- a/cashu/mint/ledger.py +++ b/cashu/mint/ledger.py @@ -187,11 +187,14 @@ class Ledger: ) return payment_request, checking_id - async def _check_lightning_invoice(self, payment_hash: str): + async def _check_lightning_invoice(self, amounts, payment_hash: str): """Checks with the Lightning backend whether an invoice with this payment_hash was paid.""" invoice: Invoice = await get_lightning_invoice(payment_hash, db=self.db) if invoice.issued: raise Exception("tokens already issued for this invoice.") + total_requested = sum([amount for amount in amounts]) + if total_requested > invoice.amount: + raise Exception(f"Requested amount too high: {total_requested}. Invoice amount: {invoice.amount}") status = await WALLET.get_invoice_status(payment_hash) if status.paid: await update_lightning_invoice(payment_hash, issued=True, db=self.db) @@ -237,9 +240,9 @@ class Ledger: # check if lightning invoice was paid if LIGHTNING: try: - paid = await self._check_lightning_invoice(payment_hash) - except: - raise Exception("could not check invoice.") + paid = await self._check_lightning_invoice(amounts, payment_hash) + except Exception as e: + raise Exception("could not check invoice: " + str(e)) if not paid: raise Exception("Lightning invoice not paid yet.") From b0f71b0c67521d829e54dfd8c642ad2594d9bec5 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 7 Oct 2022 22:52:50 +0300 Subject: [PATCH 3/6] fix: add `raise_for_status` call after HTTP calls --- cashu/wallet/wallet.py | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/cashu/wallet/wallet.py b/cashu/wallet/wallet.py index 719ffee..b32421a 100644 --- a/cashu/wallet/wallet.py +++ b/cashu/wallet/wallet.py @@ -45,10 +45,12 @@ class LedgerAPI: @staticmethod def _get_keys(url): - resp = requests.get(url + "/keys").json() + resp = requests.get(url + "/keys") + resp.raise_for_status() + data = resp.json() return { int(amt): PublicKey(bytes.fromhex(val), raw=True) - for amt, val in resp.items() + for amt, val in data.items() } @staticmethod @@ -88,6 +90,7 @@ class LedgerAPI: def request_mint(self, amount): """Requests a mint from the server and returns Lightning invoice.""" r = requests.get(self.url + "/mint", params={"amount": amount}) + r.raise_for_status() return r.json() @staticmethod @@ -130,13 +133,11 @@ class LedgerAPI: json=payloads.dict(), params={"payment_hash": payment_hash}, ) + resp.raise_for_status() try: promises_list = resp.json() except: - if resp.status_code >= 300: - raise Exception(f"Error: {f'mint returned {resp.status_code}'}") - else: - raise Exception("Unkown mint error.") + raise Exception("Unkown mint error.") if "error" in promises_list: raise Exception("Error: {}".format(promises_list["error"])) @@ -180,14 +181,11 @@ class LedgerAPI: self.url + "/split", json=split_payload.dict(), ) - + resp.raise_for_status() try: promises_dict = resp.json() except: - if resp.status_code >= 300: - raise Exception(f"Error: {f'mint returned {resp.status_code}'}") - else: - raise Exception("Unkown mint error.") + raise Exception("Unkown mint error.") if "error" in promises_dict: raise Exception("Mint Error: {}".format(promises_dict["error"])) promises_fst = [BlindedSignature.from_dict(p) for p in promises_dict["fst"]] @@ -204,28 +202,36 @@ class LedgerAPI: async def check_spendable(self, proofs: List[Proof]): payload = CheckRequest(proofs=proofs) - return_dict = requests.post( + resp = requests.post( self.url + "/check", json=payload.dict(), - ).json() - + ) + resp.raise_for_status() + return_dict = resp.json() + return return_dict async def check_fees(self, payment_request: str): """Checks whether the Lightning payment is internal.""" payload = CheckFeesRequest(pr=payment_request) - return_dict = requests.post( + resp = requests.post( self.url + "/checkfees", json=payload.dict(), - ).json() + ) + resp.raise_for_status() + + return_dict = resp.json() return return_dict async def pay_lightning(self, proofs: List[Proof], invoice: str): payload = MeltRequest(proofs=proofs, invoice=invoice) - return_dict = requests.post( + resp = requests.post( self.url + "/melt", json=payload.dict(), - ).json() + ) + resp.raise_for_status() + + return_dict = resp.json() return return_dict From eca9e95d3e862fab867c7d3b193d6fc6f49b4344 Mon Sep 17 00:00:00 2001 From: Vlad Stan Date: Fri, 7 Oct 2022 22:53:34 +0300 Subject: [PATCH 4/6] fix: falsely reporting `Invoice paid` --- cashu/wallet/cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cashu/wallet/cli.py b/cashu/wallet/cli.py index 39086ac..b11d9b1 100755 --- a/cashu/wallet/cli.py +++ b/cashu/wallet/cli.py @@ -104,12 +104,13 @@ async def mint(ctx, amount: int, hash: str): time.sleep(3) try: await wallet.mint(amount, r["hash"]) + paid = True + print("Invoice paid.") except Exception as e: + print(str(e)) if str(e) == "Error: Lightning invoice not paid yet.": print(".", end="", flush=True) continue - paid = True - print(" Invoice paid.") elif amount and hash: await wallet.mint(amount, hash) wallet.status() From 118f564d44b5e77040174b6d27f943ba47ab72fa Mon Sep 17 00:00:00 2001 From: calle <93376500+callebtc@users.noreply.github.com> Date: Fri, 7 Oct 2022 22:44:14 +0200 Subject: [PATCH 5/6] Update .env.example --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 2348d62..2b58494 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,7 @@ CASHU_DIR=~/.cashu # WALLET -# MINT_URL=http://localhost:8000/cashu/api/v1/cashu/SUVB2UrJSd9LKmn6aoSpVq +# MINT_URL=https://localhost:3338 MINT_HOST=127.0.0.1 MINT_PORT=3338 From 2877e55838154274ddf413e2250db443ba03a772 Mon Sep 17 00:00:00 2001 From: calle <93376500+callebtc@users.noreply.github.com> Date: Fri, 7 Oct 2022 22:47:13 +0200 Subject: [PATCH 6/6] Update cashu/core/settings.py --- cashu/core/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cashu/core/settings.py b/cashu/core/settings.py index b7b2ccd..6f98127 100644 --- a/cashu/core/settings.py +++ b/cashu/core/settings.py @@ -34,7 +34,7 @@ MINT_PRIVATE_KEY = env.str("MINT_PRIVATE_KEY", default=None) MINT_SERVER_HOST = env.str("MINT_SERVER_HOST", default="127.0.0.1") MINT_SERVER_PORT = env.int("MINT_SERVER_PORT", default=3338) -MINT_URL = env.str("MINT_URL") +MINT_URL = env.str("MINT_URL", default=None) MINT_HOST = env.str("MINT_HOST", default="8333.space") MINT_PORT = env.int("MINT_PORT", default=3338)